2012-01-29 11 views
142

Eventuali duplicati:
Variables inside and outside of a class __init__() functioncorretto modo per definire variabili di classe in Python

ho notato che in Python, la gente inizializzare gli attributi del loro classe in due modi diversi.

Il primo modo è come questo:

class MyClass: 
    __element1 = 123 
    __element2 = "this is Africa" 

    def __init__(self): 
    #pass or something else 

L'altro stile assomiglia:

class MyClass: 
    def __init__(self): 
    self.__element1 = 123 
    self.__element2 = "this is Africa" 

Qual è il modo corretto per inizializzare gli attributi di classe?

+3

la differenza non è grande se si usano stringhe ... ma otterrà una cosa completamente diversa se si usano dicts o liste che sono memorizzate per riferimento – Bastian

risposta

355

Entrambi i modi non sono corretti o non corretti, sono solo due tipi di elementi di classe:

  • elementi esterni del metodo __init__ sono elementi statici, significa, appartengono alla classe.
  • Gli elementi all'interno del metodo __init__ sono elementi dell'oggetto (self), non appartengono alla classe.

Vedrete più chiaramente con un po 'di codice:

class MyClass: 
    static_elem = 123 

    def __init__(self): 
     self.object_elem = 456 

c1 = MyClass() 
c2 = MyClass() 

# Initial values of both elements 
>>> print c1.static_elem, c1.object_elem 
123 456 
>>> print c2.static_elem, c2.object_elem 
123 456 

# Nothing new so far ... 

# Let's try changing the static element 
MyClass.static_elem = 999 

>>> print c1.static_elem, c1.object_elem 
999 456 
>>> print c2.static_elem, c2.object_elem 
999 456 

# Now, let's try changing the object element 
c1.object_elem = 888 

>>> print c1.static_elem, c1.object_elem 
999 888 
>>> print c2.static_elem, c2.object_elem 
999 456 

Come si può vedere, quando abbiamo cambiato l'elemento di classe, ha cambiato per entrambi gli oggetti. Ma, quando abbiamo cambiato l'elemento oggetto, l'altro oggetto è rimasto invariato.

+2

ma essendo __init__ sempre eseguito dopo che l'oggetto è stato creato, diventa praticamente uguale per definire variabili al di fuori di __init__, giusto? – jeanc

+0

la grande differenza è che gli elementi statici appartengono alla classe, non all'oggetto. Modificherò la mia risposta con un po 'più di spiegazione. – juliomalegria

+2

Se si modifica un attributo di classe (uno definito all'esterno di '__init __()') cambia per l'intera classe. Cambierà anche per altre istanze, mentre gli attributi di istanza (definiti in '__init __()') sono specifici per ogni istanza. – nitsas

7

penso che questo campione spiega la differenza tra gli stili:

[email protected]:~$cat test.py 
#!/usr/bin/env python 

class MyClass: 
    element1 = "Hello" 

    def __init__(self): 
     self.element2 = "World" 

obj = MyClass() 

print dir(MyClass) 
print "--" 
print dir(obj) 
print "--" 
print obj.element1 
print obj.element2 
print MyClass.element1 + " " + MyClass.element2 
[email protected]:~$./test.py 
['__doc__', '__init__', '__module__', 'element1'] 
-- 
['__doc__', '__init__', '__module__', 'element1', 'element2'] 
-- 
Hello World 
Hello 
Traceback (most recent call last): 
    File "./test.py", line 17, in <module> 
    print MyClass.element2 
AttributeError: class MyClass has no attribute 'element2' 

elemento1 è legato alla classe, element2 è destinato a un'istanza della classe.

+0

grazie per la tua risposta – jeanc

+3

La tua ultima affermazione non è corretta; l'oggetto non ottiene una * copia * delle variabili di classe. Tutte le istanze di una condivisione di classe accedono alle stesse variabili di classe. – Ben

+1

@ Ben hai ragione; Ho rimosso quella frase. –

Problemi correlati