我正在玩Python类,并得出以下示例,其中两个看似静态类变量的变量在修改时具有不同的行为.
这里发生了什么?我的第一直觉是引用了一些棘手的东西.
class Foo:
a = []
n = 0
def bar(self):
self.a.append('foo')
self.n += 1
x = Foo()
print x.a, x.n ([] 0)
x.bar()
print x.a, x.n (['foo', 1])
y = Foo()
print y.a, y.n (['foo', 0])
y.bar()
print y.a, y.n (['foo', 'foo'], 1)
Run Code Online (Sandbox Code Playgroud)
你是对的 - 在Foo.a访问self.a实际访问的情况下,Foo.a在所有实例之间共享Foo.但是,当您更新时self.n,+=实际上在self该阴影上创建了一个实例级变量Foo.n:
>>> import dis
>>> dis.dis(Foo.bar)
5 0 LOAD_FAST 0 (self)
3 LOAD_ATTR 0 (a)
6 LOAD_ATTR 1 (append)
9 LOAD_CONST 1 ('foo')
12 CALL_FUNCTION 1
15 POP_TOP
6 16 LOAD_FAST 0 (self)
19 DUP_TOP
20 LOAD_ATTR 2 (n)
23 LOAD_CONST 2 (1)
26 INPLACE_ADD
27 ROT_TWO
28 STORE_ATTR 2 (n)
31 LOAD_CONST 0 (None)
34 RETURN_VALUE
Run Code Online (Sandbox Code Playgroud)
换句话说,当您执行self.a.append('some value')解释a器时,通过名称从内存中提取Foo,然后改变Foo.a指向的列表.
另一方面,当你做self.n += 1翻译时:
n从Foo(因为它无法找到n上self)n + 1n上self