我正在研究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)
您是正确的-在Foo.a访问self.a实际访问的情况下Foo.a,该访问在的所有实例之间共享Foo。但是,当您进行更新时self.n,+=实际上在self该阴影上创建了一个实例级变量Foo.n:
Foo.a
self.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
换句话说,当您执行self.a.append('some value')此操作时,解释a器将通过名称on从内存中获取数据Foo,然后对Foo.a指向的列表进行变异。
self.a.append('some value')
a
另一方面,当您执行self.n += 1口译员时:
self.n += 1
n
n + 1