2016-12-13 4 views
0

私は以下のPythonの動作に困惑しています。なぜ2番目と3番目のインスタンスの属性(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 
+1

「int is int」の結果を解釈することに注意してください... Pythonは小さな整数をキャッシュします。おそらく、そのようなデモンストレーションにはダミーのクラスを使用する方がよいでしょうが、この場合、デモンストレーションには影響しないとは思いません。 –

答えて

6

ここでは何が起こりますか。あなたが行うと:

a.i = 1 

あなたが名前のインスタンス変数を作成することクラス属性。クラス属性は、しかし、まだそこにある:

>>> 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 

インスタンスの辞書をチェックし、インスタンスの名前空間に住んでいるかを確認するには:あなたが意図したとおりに

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

a.i = 1Foo.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}) 
関連する問題