Cas*_*ash 14 python local-variables
locals是一个内置函数,返回本地值的字典.文件说:
警告
不应修改此词典的内容; 更改可能不会影响解释器使用的局部变量的值.
不幸的是,exec在Python 3.0中也有同样的问题.这有什么办法吗?
用例
考虑:
@depends("a", "b", "c", "d", "e", "f")
def test():
put_into_locals(test.dependencies)
Run Code Online (Sandbox Code Playgroud)
depends将其参数中提供的字符串存储在列表中test.dependences.这些字符串是字典中的键d.我希望能够编写,put_into_locals以便我们可以将值拉出d并将它们放入本地.这可能吗?
Unk*_*own 14
我刚刚测试了exec,它适用于Python 2.6.2
>>> def test():
... exec "a = 5"
... print a
...
>>> test()
5
Run Code Online (Sandbox Code Playgroud)
如果您使用的是Python 3.x,则它不再起作用,因为locals在运行时被优化为数组,而不是使用字典.
当Python检测到"exec语句"时,它将强制Python将本地存储从数组切换到字典.但是由于"exec"是Python 3.x中的一个函数,编译器无法进行这种区分,因为用户可能已经完成了类似"exec = 123"的操作.
http://bugs.python.org/issue4831
如果没有几个结果,则无法动态修改函数的局部函数:通常,函数局部函数不存储在字典中,而是存储在数组中,其索引在编译时从已知语言环境确定.这至少与exec添加的新本地人发生冲突.旧的exec语句规避了这一点,因为编译器知道如果函数中没有发生全局/局部因子的exec,那么该命名空间将"未经优化",即不使用本地数组.由于exec()现在是一个普通函数,编译器不知道"exec"可能绑定到什么,因此无法特别处理.
局部变量由赋值语句修改.
如果你有字符串的字符串键,请不要使它们成为局部变量 - 只需将它们用作字典键.
如果你绝对必须 有局部变量这样做.
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 )
Run Code Online (Sandbox Code Playgroud)
这将填充你的字典中的一些局部变量而不做任何神奇的事情.
这是不可能的。我认为这是为了以后进行性能优化。Python 字节码通过索引而不是名称引用局部变量;如果 locals() 被要求是可写的,它可能会阻止解释器实现一些优化,或者使它们变得更加困难。
我相当肯定您不会找到任何保证您可以像这样编辑本地人的核心 API,因为如果该 API 可以做到,那么 locals() 也不会受到此限制。
不要忘记所有本地变量在编译时都必须存在;如果在编译时引用未绑定到本地的名称,则编译器会假定它是全局的。编译后不能“创建”本地人。
请参阅此问题以获取一种可能的解决方案,但这是一个严重的问题,您真的不想这样做。
请注意,您的示例代码存在一个基本问题:
@depends("a", "b", "c", "d", "e", "f")
def test():
put_into_locals(test.dependencies)
Run Code Online (Sandbox Code Playgroud)
"test.dependencies"不是指“f.dependencies”,其中 f 是当前函数;它引用了实际的全局值“test”。这意味着如果您使用多个装饰器:
@memoize
@depends("a", "b", "c", "d", "e", "f")
def test():
put_into_locals(test.dependencies)
Run Code Online (Sandbox Code Playgroud)
它将不再起作用,因为“test”是 memoize 的包装函数,而不是depends。Python确实需要一种方法来引用“当前正在执行的函数”(和类)。