2013-05-29 9 views
6

私はPythonクラスで遊んでいましたが、静的クラス変数と思われる2つの変数が変更されたときの動作が異なります。Pythonクラス変数int vs array

ここでは何が起こっていますか?私の最初の本能は、何かトリッキーなことが参考になるということです。

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) 
+1

は、pythonで注意する同様のケースです。http://stackoverflow.com/questions/101268/hidden-features-of-python#113198 – qwwqwwq

答えて

5

あなたは正しいです - self.aにアクセスFoo.aの場合には、実際にFooのすべてのインスタンス間で共有されているFoo.aを、アクセスします。そして、言い換えれば

>>> 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')を行う際に通訳がFooに名前を介してメモリからaを取り出し、:しかし、あなたは+=self.nを更新するとき、あなたは実際にFoo.nをシャドウself上のインスタンス・レベルの変数を作成しますFoo.aが指すリストを変更します。一方

、あなたがself.n += 1インタプリタを実行します。(それはselfnを見つけることができないため)

  • Fooからnを取得し
  • は、新しい値n + 1
  • 店舗作成します属性内の新しい値self
+0

Gotcha。影を引き起こす割り当ては '+ ='の後ろで(私にとって)難読化されました。ありがとう! – mcamac