2013-05-29 24 views
6

Stavo giocando con le classi Python e sono arrivato al seguente esempio in cui due variabili che sembrano variabili di classe statiche hanno un comportamento diverso quando vengono modificate.Variabile di classe Python int vs array

Cosa sta succedendo qui? Il mio primo istinto è che qualcosa di complicato sta succedendo con i riferimenti.

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

Ecco un caso simile da tenere a mente in python http://stackoverflow.com/questions/101268/hidden-features-of-python#113198 – qwwqwwq

risposta

5

Siete corretto - nel caso di accesso Foo.aself.a accede in realtà Foo.a, che è condiviso tra tutte le istanze di Foo. Tuttavia, quando si aggiorna self.n con += di creare effettivamente una variabile a livello di istanza sul self che le ombre 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  

In altre parole, quando si esegue self.a.append('some value') l'interprete recupera a dalla memoria tramite un nome su Foo e poi muta la lista a cui punta Foo.a.

D'altra parte, quando si fa self.n += 1 l'interprete:

  • recupera n da Foo (perché non riesce a trovare il nself)
  • Crea un nuovo valore n + 1
  • Memorizza i nuovo valore nell'attributo n su self
+0

Gotcha. L'incarico che causa l'ombra è stato (per me) offuscato dietro il '+ ='. Grazie! – mcamac