pin*_*aas 11 python attributes scope class function
在引用全局变量时,可以看到函数和类以不同方式处理它.第一个很好,第二个导致错误:
x = 10
class Foo():
x = x + 1
a = foo()
Run Code Online (Sandbox Code Playgroud)
VS:
x = 10
def faa():
x = x + 1
faa()
Run Code Online (Sandbox Code Playgroud)
在 Python执行模型中,这被描述为:
类定义是可以使用和定义名称的可执行语句.这些引用遵循名称解析的常规规则,但在全局命名空间中查找未绑定的局部变量.
但为什么?
唯一的其他提示我所遇到的是该位:
然后使用新创建的本地命名空间和原始全局命名空间,在新的执行框架中执行类的套件(请参阅命名和绑定一节).(通常,套件仅包含函数定义.)当类的套件完成执行时,其执行帧将被丢弃,但其本地名称空间将被保存.4然后使用基类的继承列表和属性字典的已保存本地名称空间创建类对象.
这仍然没有解释为什么这应该导致在全局命名空间中查找未绑定的本地人.
这两个链接都来自这个答案,虽然没有详细说明原因.
正如 Python 常见问题解答中所述- 为什么我会收到 UnboundLocalError?
...因为当您对作用域中的变量进行赋值时,该变量将成为该作用域的本地变量,并隐藏外部作用域中任何类似命名的变量。由于 foo 中的最后一条语句为 x 分配了一个新值,因此编译器将其识别为局部变量。
因此,当早些时候尝试访问未初始化的局部变量时,会出现错误。
这解释了为什么:
x = 10
def foo():
x = x+1 # raises UnboundLocalError
foo()
Run Code Online (Sandbox Code Playgroud)
引发异常,但不是这样:
x = 10
def faa():
y = x+1 # x stays in global scope, since it is not assigned in local
faa()
Run Code Online (Sandbox Code Playgroud)
对于class foo()它来说是相同的,因为 python 允许在任何给定时间将属性分配给对象。类代码指定x为对象的新属性a。
x = 10
class foo():
x = x+1 # scope of x: class
a = foo() # x = 10; a.x = foo.x = 11
Run Code Online (Sandbox Code Playgroud)
是相同的:
x = 10
class foo():
def __init__(self):
self.x = x+1 # scope of x: instance
a = foo() # x = 10; a.x = 11
Run Code Online (Sandbox Code Playgroud)
其中显然self.x是被分配而不是x,因此也停留在全局范围内。(另请参阅此处)