在下面的代码中,如果在函数 foo 中对名称 v 使用赋值语句,解释器将给出 unboundlocalerror,因为这在函数作用域中创建了一个同名变量,我们尝试在本地分配之前引用它。但是为什么在实例方法中对实例变量做同样的事情不会给出任何错误? Python 计算 self.v = self.v + 1
和 v = v + 1
时有什么区别?
class A:
v = 1
def foo(self):
self.v = self.v + 1
v = 1
def foo():
v = v + 1
# UnboundLocalError: local variable 'v' referenced before assignment
foo()
a = A()
# print 1
print(a.v)
a.foo()
# print 1 2
print(a.__class__.v, a.v)
答案 0 :(得分:2)
局部变量解析是静态的。在字节码编译时,Python 识别出 foo
有一个 v
局部变量,因此所有对 v
中的 foo
的访问都转到局部变量,即使局部变量是未绑定。
实例属性解析是动态的。每当执行 self.v
访问时,Python 都会搜索继承层次结构中的实例 dict 和类 dicts 以确定 v
应该是什么。 (除非定义了其他一些自定义行为,否则分配总是转到实例字典。)
与局部变量不同,对 self.v
赋值的存在本身不会影响属性访问解析为什么,并且 self.v
的重复访问可能会以不同的方式解析;一次访问可能在实例 dict 中找不到任何内容并解析为类 dict 中的 'v'
条目,而稍后的条目可能会发现到那时实例 dict 中存在 'v'
条目,并解析为