2014-04-25 12 views
29

Jestem całkiem nowy, python, i zauważyłem te posty: Python __init__ and self what do they do? i Python Classes without using def __init__(self)Przydatność def __init __ (self)?

Po zabawy z nim, jednak zauważyłem, że te dwie klasy dać najwyraźniej odpowiednik WYNIKI

class A(object): 
    def __init__(self): 
     self.x = 'Hello' 

    def method_a(self, foo): 
     print self.x + ' ' + foo 

(od this question)

i

class B(object): 
    x = 'Hello' 
    def method_b(self,foo): 
     print self.x + ' ' + foo 

Czy istnieje jakaś różnica między tymi dwoma? Lub, bardziej ogólnie, czy zmiana nieodłącznie dotyczy atrybutów klasy? W dokumencie the documentation wspomniano, że __init__ jest wywoływane podczas tworzenia instancji. Czy to oznacza, że ​​x w klasie B jest ustanowiony przed instancją?

Odpowiedz

32

Tak, to sprawdzić:

class A(object): 
    def __init__(self): 
     self.lst = [] 

class B(object): 
    lst = [] 

i teraz spróbuj:

>>> x = B() 
>>> y = B() 
>>> x.lst.append(1) 
>>> y.lst.append(2) 
>>> x.lst 
[1, 2] 
>>> x.lst is y.lst 
True 

a to:

>>> x = A() 
>>> y = A() 
>>> x.lst.append(1) 
>>> y.lst.append(2) 
>>> x.lst 
[1] 
>>> x.lst is y.lst 
False 

Czy to znaczy, że x w klasie B jest ustanowiony przed utworzeniem?

Tak, jest to atrybut klasy (jest dzielony między instancjami). W klasie A jest atrybutem instancji. Zdarza się, że ciągi są niezmienne, a zatem nie ma żadnej różnicy w twoim scenariuszu (z wyjątkiem tego, że klasa B zużywa mniej pamięci, ponieważ definiuje tylko jeden ciąg dla wszystkich instancji). Ale w moim przykładzie jest ogromny.

+2

+1 Nie zapomnij, że skoro zajęcia są obiekty można zmienić atrybut klasy, sam, w dowolnym czasie. 'class A: pass; A.lst = list (range (6))'. – kojiro

9

W pierwszym przykładzie masz zmienną instancji klasy. Ta zmienna jest dostępna tylko poprzez instancję (wymaganą przez użytkownika).

class A(): 
    def __init__(self): 
     self.x = 'hello' 

print A.x -> AttributeError 
print A().x -> 'hello' 

W drugim przykładzie mamy zmienną statyczną. Możesz uzyskać dostęp do tej zmiennej, dzięki nazwą klasy A

class A(): 
    x = 'hello' 

print A.x -> 'hello' 
print A().x -> 'hello' 

W rzeczywistości można mieć statyczny i zmiennej instancji o tej samej nazwie:

class A(): 
    x = 'hello' 
    def __init__(self): 
     self.x = 'world' 

print A.x -> hello 
print A().x -> world 

Wartość statyczne dzielonego między wszystkie instancje

class A(): 
    x = 'hello' 

    @staticmethod 
    def talk(): 
     print A.x 

a = A() 
print a.talk() -> hello 

A.x = 'world' 
print a.talk() -> world 

mieć dobry artykuł tutaj: http://linuxwell.com/2011/07/21/static-variables-and-methods-in-python/

4

Jak stwierdzili inni, jest to różnica między zmienną w klasie a zmienną w instancji klasy instancji. Zobacz następujący przykład.

>>> class A: 
...  a = [] 
... 
>>> class B: 
...  def __init__(self): 
...   self.b = [] 
... 
>>> a1 = A() 
>>> a1.a.append('hello') 
>>> a2 = A() 
>>> a2.a 
['hello'] 
>>> b1 = B() 
>>> b1.b.append('goodbye') 
>>> b2 = B() 
>>> b2.b 
[] 

Dla niezmiennych obiektów takich jak krotek, sznurków itp trudniej jest zauważyć różnicę, ale dla mutables, zmienia wszystko — zmiany stosowane są dzielone pomiędzy wszystkich wystąpień tej klasy.

Należy również zauważyć, że takie samo zachowanie zachodzi w przypadku domyślnych argumentów słów kluczowych!

>>> class A: 
...  def __init__(self, a=[]): 
...   a.append('hello') 
...   print(a) 
... 
>>> A() 
['hello'] 
>>> A() 
['hello', 'hello'] 
>>> A() 
['hello', 'hello', 'hello'] 

>>> class B: 
...  def __init__(self, b=None): 
...   if b is None: 
...    b = [] 
...   b.append('goodbye') 
...   print(b) 
... 
>>> B() 
['goodbye'] 
>>> B() 
['goodbye'] 
>>> B() 
['goodbye'] 

To zachowanie gryzie wielu nowych programistów w języku Python. Dobrze, że wcześnie odkrywasz te różnice!

0

użyć init, nie trzeba go używać w twoim przypadku można po prostu

enter code here 

class some(): 
    def main(self): 
     self.x=10 
    def mathod_a(self,foo): 
     print self.x+foo' 

a jeśli chcesz używać startowych spróbować

enter code here 
class some(): 
def main(self): 
    print(x) 
def init(self,x): 
    self.x=x 
    main() 
Powiązane problemy