6

我在玩 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)
4

1 回答 1

5

你是对的 - 在Foo.a访问self.a实际访问的情况下Foo.a,它在所有实例之间共享Foo。但是,当您更新self.n时,实际上会在该 shadows+=上创建一个实例级变量:selfFoo.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器通过名称从内存中获取Foo,然后改变Foo.a指向的列表。

另一方面,当你做self.n += 1解释器时:

  • 取自(因为n在上Foo找不到)nself
  • 创造新价值n + 1
  • 将新值存储在属性nself
于 2013-05-29T04:48:41.667 回答