python - 如何将此 Python 2.7 代码转换为 Python 3?
问题描述
以下代码适用于 Python 2.7,用于将局部变量动态注入函数范围:
myvars = {"var": 123}
def func():
exec("")
locals().update(myvars)
print(var)
func()
# assert "var" not in globals()
这有点微妙,但是 exec 语句的存在向编译器表明本地命名空间可能被修改。在参考实现中,它将名称“locals”的查找从 LOAD_GLOBAL 操作转换为 LOAD_NAME 操作,从而可以添加到本地命名空间。
在 Python 3 中,exec
变成了一个函数而不是一个语句,并且locals()
调用返回了命名空间的副本,其中的修改没有任何效果。
如何在 Python 3 中重新创建这个想法,在函数内动态创建局部变量?或者这是仅在 Python 2.x 中才有的“功能”?
注意:代码不得绑定外部范围内的名称。
解决方案
我不推荐它,但您可以将函数的主体放在类语句中:
myvars = {"var": 123}
def func():
class Bleh:
locals().update(myvars)
print(var)
func()
与 Python 2 代码一样,locals()
在这种情况下修改工作的事实在技术上没有记录,并且可能会发生变化。类作用域必须使用实际的 dict 来解析局部变量,但理论上,以后的 Python 实现可能会复制该 dictlocals()
或类似的东西。
与 Python 2 代码一样,这样做会干扰闭包变量解析,包括以下微妙情况:
myvars = {"var": 123}
def func():
class Bleh:
locals().update(myvars)
print([var for x in (1, 2, 3)])
func()
甚至
def func():
class Bleh:
var = 123
print([var for x in (1, 2, 3)])
func()
这两种情况都会导致 NameError,因为列表推导式创建了一个无法访问var
.
在 Python 2 中,尝试使用闭包变量exec
会导致 SyntaxError。如果您尝试使用 class 语句复制 Python 3 中的功能,则不会得到任何此类检测。
最后,Python将在 class 语句完成后尝试构建一个类,这可能会导致一些奇怪的问题,例如__set_name__
方法意外运行。您至少可以通过使用元类来解决此问题:
class NoClass(type):
def __new__(self, *args, **kwargs):
return None
def func():
class Bleh(metaclass=NoClass):
...
推荐阅读
- python - Python Post 请求 - 通过 Outlook API 发送文件时出现 415 错误
- r - 将 data.frame 导出到 xlsx
- c# - 如何防止“索引”在 Action 数组中更新自身
- html - 如何在 XPath/CSS 定位器中排除一个孩子
- c++ - 无法通过 QModelIndex 从 QTreeView 获取项目
- database - 如何从 Visual Studio 2017 将 localdb 发布到 Azure
- azure - Visual Studio 2019 中缺少 Application Insights
- android - React Native 中的序列动画
- c# - 如何找到浏览器当前的显示语言?
- kotlin - != null VS ?.let { } kotlin 中不可变变量的性能