python 有什么办法可以修改locals字典吗?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1450275/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Any way to modify locals dictionary?
提问by Casebash
locals
is a built in function that returns a dictionary of local values. The documentation says:
locals
是一个内置函数,它返回一个本地值的字典。文档说:
Warning
The contents of this dictionary should not be modified; changes may not affect the values of local variables used by the interpreter.
警告
本词典内容不得修改;更改可能不会影响解释器使用的局部变量的值。
Unfortunately, exec has the same problem in Python 3.0. Is there any way round this?
不幸的是, exec 在 Python 3.0 中也有同样的问题。有没有办法解决这个问题?
Use Case
用例
Consider:
考虑:
@depends("a", "b", "c", "d", "e", "f")
def test():
put_into_locals(test.dependencies)
depends stores the strings provided in its arguments in a list test.dependences
. These strings are keys in a dictionary d
. I would like to be able to able to write put_into_locals
so that we could pull the values out of d
and put them into the locals. Is this possible?
依赖将其参数中提供的字符串存储在列表中test.dependences
。这些字符串是字典中的键d
。我希望能够编写,put_into_locals
以便我们可以将值提取出来d
并将它们放入本地。这可能吗?
采纳答案by Unknown
I just tested exec and it works in Python 2.6.2
我刚刚测试了 exec,它在 Python 2.6.2 中工作
>>> def test():
... exec "a = 5"
... print a
...
>>> test()
5
If you are using Python 3.x, it does not work anymore because locals are optimized as an array at runtime, instead of using a dictionary.
如果您使用的是 Python 3.x,它不再起作用,因为本地变量在运行时被优化为数组,而不是使用字典。
When Python detects the "exec statement", it will force Python to switch local storage from array to dictionary. However since "exec" is a function in Python 3.x, the compiler cannot make this distinction since the user could have done something like "exec = 123".
当 Python 检测到“exec 语句”时,它会强制 Python 将本地存储从数组切换到字典。然而,由于“exec”是 Python 3.x 中的一个函数,编译器无法进行这种区分,因为用户可以执行诸如“exec = 123”之类的操作。
http://bugs.python.org/issue4831
http://bugs.python.org/issue4831
To modify the locals of a function on the fly is not possible without several consequences: normally, function locals are not stored in a dictionary, but an array, whose indices are determined at compile time from the known locales. This collides at least with new locals added by exec. The old exec statement circumvented this, because the compiler knew that if an exec without globals/locals args occurred in a function, that namespace would be "unoptimized", i.e. not using the locals array. Since exec() is now a normal function, the compiler does not know what "exec" may be bound to, and therefore can not treat is specially.
动态修改函数的局部变量是不可能的,但不会产生多种后果:通常,函数局部变量不存储在字典中,而是一个数组,其索引在编译时根据已知的语言环境确定。这至少与 exec 添加的新本地人发生冲突。旧的 exec 语句绕过了这一点,因为编译器知道如果在函数中发生没有 globals/locals args 的 exec,那么该命名空间将是“未优化的”,即不使用 locals 数组。由于 exec() 现在是一个普通函数,编译器不知道“exec”可能绑定到什么,因此不能特殊对待。
回答by S.Lott
The local variables are modified by assignment statements.
局部变量由赋值语句修改。
If you have dictionary keys which are strings, please don't also make them local variables -- just use them as dictionary keys.
如果您有字符串形式的字典键,请不要同时将它们设为局部变量——只需将它们用作字典键即可。
If you absolutely musthave local variables do this.
如果您绝对必须有局部变量,请执行此操作。
def aFunction( a, b, c, d, e, f ):
# use a, b, c, d, e and f as local variables
aFunction( **someDictWithKeys_a_b_c_d_e_f )
That will populate some local variables from your dictionary without doing anything magical.
这将从您的字典中填充一些局部变量,而不会做任何神奇的事情。
回答by Glenn Maynard
This isn't possible. I think this is to allow for performance optimizations later on. Python bytecode references locals by index, not by name; if locals() was required to be writable, it could prevent interpreters from implementing some optimizations, or make them more difficult.
这是不可能的。我认为这是为了以后进行性能优化。Python 字节码通过索引而不是名称引用局部变量;如果 locals() 被要求是可写的,它可能会阻止解释器实现一些优化,或者使它们变得更加困难。
I'm fairly certain you're not going to find any core API that guarantees you can edit locals like this, because if that API could do it, locals() wouldn't have this restriction either.
我相当肯定您不会找到任何保证您可以像这样编辑本地人的核心 API,因为如果该 API 可以做到,那么 locals() 也不会受到此限制。
Don't forget that all locals must exist at compile-time; if you reference a name that isn't bound to a local at compile-time, the compiler assumes it's a global. You can't "create" locals after compilation.
不要忘记所有本地变量在编译时都必须存在;如果在编译时引用未绑定到本地的名称,则编译器会假定它是全局的。编译后不能“创建”本地人。
See this questionfor one possible solution, but it's a serious hack and you really don't want to do that.
请参阅此问题以获取一种可能的解决方案,但这是一个严重的问题,您真的不想这样做。
Note that there's a basic problem with your example code:
请注意,您的示例代码存在一个基本问题:
@depends("a", "b", "c", "d", "e", "f")
def test():
put_into_locals(test.dependencies)
"test.dependencies"
isn't referring to "f.dependencies" where f is the current function; it's referencing the actual global value "test". That means if you use more than one decorator:
"test.dependencies"
不是指“f.dependencies”,其中 f 是当前函数;它引用了实际的全局值“test”。这意味着如果您使用多个装饰器:
@memoize
@depends("a", "b", "c", "d", "e", "f")
def test():
put_into_locals(test.dependencies)
it'll no longer work, since "test" is memoize's wrapped function, not depends's. Python reallyneeds a way to refer to "the currently-executing function" (and class).
它将不再起作用,因为“test”是 memoize 的包装函数,而不是depends 的。Python确实需要一种方法来引用“当前正在执行的函数”(和类)。
回答by David Pennell
I would store it in a variable:
我会将它存储在一个变量中:
refs = locals()
def set_pets():
global refs
animals = ('dog', 'cat', 'fish', 'fox', 'monkey')
for i in range(len(animals)):
refs['pet_0%s' % i] = animals[i]
set_pets()
refs['pet_05']='bird'
print(pet_00, pet_02, pet_04, pet_01, pet_03, pet_05 )
>> dog fish monkey cat fox bird
And if you want to test your dict before putting it in locals():
如果你想在将它放入 locals() 之前测试你的 dict:
def set_pets():
global refs
sandbox = {}
animals = ('dog', 'cat', 'fish', 'fox', 'monkey')
for i in range(len(animals)):
sandbox['pet_0%s' % i] = animals[i]
# Test sandboxed dict here
refs.update( sandbox )
Python 3.6.1 on MacOS Sierra
MacOS Sierra 上的 Python 3.6.1
回答by dcrosta
I'm not sure if it is subject to the same restrictions, but you can get a direct reference to the current frame (and from there, the local variables dictionary) through the inspect module:
我不确定它是否受到相同的限制,但您可以通过检查模块获得对当前帧(以及从那里,局部变量字典)的直接引用:
>>> import inspect
>>> inspect.currentframe().f_locals['foo'] = 'bar'
>>> dir()
['__builtins__', '__doc__', '__name__', '__package__', 'foo', 'inspect']
>>> foo
'bar'