wim*_*wim 5 python cpython local-variables python-2.7 python-3.x
The following code works in Python 2.7, to dynamically inject local variables into a function scope:
myvars = {"var": 123}
def func():
exec("")
locals().update(myvars)
print(var)
func()
# assert "var" not in globals()
Run Code Online (Sandbox Code Playgroud)
这有点微妙,但是exec语句的存在向编译器指示可以修改本地名称空间。在参考实现中,它将把名称“ locals”的查找从LOAD_GLOBAL op转换为LOAD_NAME op,从而允许添加到本地名称空间。
在Python 3中,它exec变成了函数而不是语句,并且该locals()调用返回了名称空间的副本,其中的修改无效。
您如何在Python 3中重新创建想法,以便在函数内部动态创建局部变量?还是仅在Python 2.x中才有“功能”?
注意:该代码不得在外部范围内绑定名称。
我不推荐它,但你可以将函数的主体放在类语句中:
myvars = {"var": 123}
def func():
class Bleh:
locals().update(myvars)
print(var)
func()
Run Code Online (Sandbox Code Playgroud)
与 Python 2 代码一样,在这种情况下修改工作的事实locals()在技术上没有记录,并且可能会发生变化。类作用域必须使用实际的字典进行局部变量解析,但理论上,稍后的 Python 实现可能会复制该字典locals()或类似的内容。
与 Python 2 代码一样,这样做会干扰闭包变量解析,包括如下微妙情况:
myvars = {"var": 123}
def func():
class Bleh:
locals().update(myvars)
print([var for x in (1, 2, 3)])
func()
Run Code Online (Sandbox Code Playgroud)
甚至
def func():
class Bleh:
var = 123
print([var for x in (1, 2, 3)])
func()
Run Code Online (Sandbox Code Playgroud)
这两种情况都会导致 NameError,因为列表推导式创建了一个无法访问var.
在 Python 2 中,尝试使用闭包变量 withexec会导致语法错误。如果您尝试使用类语句复制 Python 3 中的功能,则不会得到任何此类检测。
最后,Python将在类语句完成后尝试构建一个类,这可能会导致奇怪的问题,例如__set_name__方法意外运行。您至少可以通过使用元类来解决此问题:
class NoClass(type):
def __new__(self, *args, **kwargs):
return None
def func():
class Bleh(metaclass=NoClass):
...
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
91 次 |
| 最近记录: |