为什么更改实例变量也会改变静态变量?

时间:2016-12-13 23:57:11

标签: python class attributes

我对下面的Python行为感到困惑。为什么第二个和第三个实例(bc),i的属性是类属性i,但a的行为有所不同?

In [47]: class Foo:
    ...:     i=0
    ...:

In [48]: a = Foo()

In [49]: a.i = 1

In [50]: a.i
Out[50]: 1

In [51]: Foo.i
Out[51]: 0

In [52]: b = Foo()

In [53]: b.i
Out[53]: 0

In [54]: Foo.i is b.i
Out[54]: True

In [55]: Foo.i is a.i
Out[55]: False

In [56]: c = Foo()

In [57]: Foo.i is c.i
Out[57]: True

2 个答案:

答案 0 :(得分:6)

这里发生了什么。当你这样做时:

a.i = 1

您创建一个名为 shadows class属性的实例变量。但是,class属性仍然存在:

>>> class Foo:
...     i = 0
...     
>>> a = Foo()
>>> Foo.i
0
>>> a.i = 69
>>> a.i
69
>>> a.__class__.i
0
>>> del a.i  # deletes the instance attribute, resolving lookup on class
>>> a.i
0

要查看实例命名空间中的内容,请查看实例dict:

>>> a = Foo()
>>> a.__dict__
{}
>>> a.i = 1
>>> a.__dict__
{'i': 1}

答案 1 :(得分:0)

a.i = 1不会按预期更改Foo.i。它更确定了a的实例成员。很明显,如果您看到a.__dict__b.__dict__

In [11]: a.__dict__
Out[11]: {'i': 1}

In [13]: b.__dict__
Out[13]: {}

如果您想真正更改类成员变量,则应使用Foo.i = 1。这将影响所有Foo个实例。同样,在Foo.__dict__上非常清楚。

In [17]: Foo.__dict__
Out[17]: 
mappingproxy({'__dict__': <attribute '__dict__' of 'Foo' objects>,
              '__doc__': None,
              '__module__': '__main__',
              '__weakref__': <attribute '__weakref__' of 'Foo' objects>,
              'i': 0})