您好, 欢迎来到 !    登录 | 注册 | | 设为首页 | 收藏本站

如何在Python中解析对变量的引用

如何在Python中解析对变量的引用

用两个词来说,示例5和示例6之间的区别在于,示例5中的变量x也被分配到相同的范围内,而示例6中没有。这触发了可以由历史原因理解的差异。

这引发了UnboundLocalError:

x = "foo"
def f():
    print x
    x = 5
f()

而不是打印“ foo”。即使一开始看起来很奇怪,这还是有道理的:函数f()在x本地定义了变量,即使它在打印之后也是如此,因此x在同一函数中对它的任何引用都必须是对该局部变量的引用。至少这是有道理的,如果您错误地在本地重用了全局变量名称,并试图同时使用全局变量和局部变量,则可以避免意外的意外。这是一个好主意,因为这意味着我们可以静态地知道,只要看一眼变量, 意味着变量。例如,我们知道这里print x引用了局部变量(因此可能引发UnboundLocalError):

x = "foo"
def f():
    if some_condition:
        x = 42
    print x
f()

现在,此规则不适用于类级范围:在那里,我们希望表达式x = x能够正常工作,将全局变量捕获x到类级范围中。这意味着类级别的作用域不遵循上面的基本规则:例如,我们不知道x该作用域中是指某个外部变量还是本地定义的x-–:

class X:
    x = x     # we want to read the global x and assign it locally
    bar = x   # but here we want to read the local x of the prevIoUs line

class Y:
    if some_condition:
        x = 42
    print x     # may refer to either the local x, or some global x

class Z:
    for i in range(2):
        print x    # prints the global x the 1st time, and 42 the 2nd time
        x = 42

因此,在类范围内,使用了不同的规则:通常会引发UnboundLocalError的地方—仅在这种情况下— 而是在模块全局变量中查找。仅此而已:它不遵循嵌套作用域链。

为什么不?我实际上怀疑有一个更好的解释是“出于历史原因”。用更专业的术语来说,它可以认为该变量x既在类作用域中本地定义(因为已被分配给它), 应从父作用域作为词法嵌套变量传递(因为已被读取)。可以通过使用与LOAD_NAME在本地作用域中查找的字节码不同的字节码来实现它,如果未找到,则退回到使用嵌套作用域的引用。

感谢wilberforce对http://bugs.python.org/issue532860的引用。如果我们认为毕竟应该修复该问题,那么我们可能有机会用提议的新字节码重新进行一些讨论(错误报告考虑终止对它的支持x = x但由于担心破坏太多现有代码而被关闭;相反,我是我建议这里将x = x在更多情况下进行工作)。否则我可能会错过另一个要点…

似乎cpython在当前的3.4主干中确实做到了这一点:http ://bugs.python.org/issue17853 … …还是不?他们介绍字节码的原因略有不同,因此没有系统地使用它。

python 2022/1/1 18:36:47 有240人围观

撰写回答


你尚未登录,登录后可以

和开发者交流问题的细节

关注并接收问题和回答的更新提醒

参与内容的编辑和改进,让解决方法与时俱进

请先登录

推荐问题


联系我
置顶