2013-07-09 8 views
5

Jestem bardzo nowy w programowaniu i zacząłem uczyć się Pythona. Może wyglądać bardzo głupio, więc proszę, wybacz mi moją ignorancję. Rozważmy następujący fragment kodu:Opis atrybutów klasy Python

class Test1: 
    bar = 10  
    def display(self,foo): 
     self.foo=foo 
     print "foo : ",self.foo #80 
    def display1(self): 
     print "bar: ", self.bar #10 
     print "again foo: ", self.foo #80 

if __name__ == '__main__': 
    test1 = Test1() 
    test1.display(80) 
    test1.display1() 
    print test1.bar #10 
    print test1.foo #80 

Chcę zrozumieć, jaka jest różnica między używaniem foo i bar (wrt do miejsca, gdzie zostały one zdefiniowane), jak w zakresie mądry są jednakowo dostępne we wszystkich miejscach, w porównaniu do nawzajem i jedyną różnicą jest to, że jedna znajduje się wewnątrz funkcji, a druga w klasie, ale obie nadal są zmiennymi "instancji". Więc co jest dobrą praktyką?

Ponadto, jeśli nieco zmodyfikować funkcję jak poniżej wyświetlacza:

def display(self,foo): 
     self.foo=foo 
     foo = foo 
     print "self.foo : ",self.foo 
     print "foo : ",foo 

Może ktoś proszę wyjaśnić, jak pyton widzi to, co za różnica jak w/znaczeniu tego słowa kluczowego self przynosi między dwoma foo.

+4

Nie, 'bar' to * nie * jest zmienną instancji. Oba są bardzo różne, dlatego nie chodzi o "dobrą praktykę". Chodzi o to, co jest odpowiednie dla twojej sytuacji, ponieważ służą one różnym celom. – phant0m

+1

Również 'self.bar' działa, ponieważ nazwa' bar' jest najpierw przeszukiwana w przestrzeni nazw instancji, a następnie w klasie. Fakt, że 'self.bar' działa, nie zawsze oznacza, że' bar' jest zmienną instancji. – ersran9

Odpowiedz

3

bar jest atrybutem klasy. Ponieważ klas Python są obiektami, one również mogą mieć atrybuty: bar po prostu dzieje się na tym obiekcie Test, a nie jego instancji.

Ze względu na sposób, w jaki Python rozwiązuje wyszukiwanie atrybutów, wygląda na to, że test1 ma atrybut bar, ale tak się nie dzieje.

foo z drugiej strony żyje na instancji test1 po wywołaniu display(80). Oznacza to, że różne instancje Test mogą mieć różne wartości w ich odpowiednich atrybutach foo.

Oczywiście, możesz użyć zmiennych klasowych jako pewnego rodzaju "współdzielonej wartości domyślnej", którą możesz następnie "przesłonić" za pomocą atrybutu instancji, ale może to być mylące.

Drugie pytanie

def display(self,foo): 
    self.foo=foo 
    foo = foo 
    print "self.foo : ",self.foo 
    print "foo : ",foo 

Powiedzmy po prostu szczegół z drogi: self nie jest słowem kluczowym, to tylko konwencja zadzwonić pierwszy argument „ja”, można także nazwać „to "lub" to "lub" bar ", jeśli ci się podobało, ale nie polecam tego.

Python przekaże obiekt, na którym metoda została wywołana jako pierwszy argument.

def display(self,foo): 

To foo jest nazwą pierwszego parametru funkcji wyświetlania.

self.foo=foo 

Ustawia atrybut o nazwie „foo” instancji, na których nazwie display() do wartości, która została przekazana jako pierwszy argument. Na tym przykładzie test1.display(80), self będzie test1, foo jest 80 i zostanie więc ustawiony na 80.

foo = foo 

To nic nie robi. Odwołuje się do pierwszego parametru foo.

Kolejne dwie linie ponownie odnoszą się do zmiennej instancji foo i pierwszego parametru foo.

4

bar jest atrybutem klasy, a foo jest atrybutem instancji. Główną różnicą jest to, że bar będą dostępne dla wszystkich instancji klasy podczas foo będzie dostępny do instancji tylko jeśli zadzwonisz wyświetlacz na tej instancji

>>> ins1 = Test1() 

ins1.bar działa prawidłowo, gdyż jest atrybutem klasy i jest wspólna dla wszystkich instancje.

>>> ins1.bar 
10 

Ale nie można uzyskać dostępu foo bezpośrednio tutaj, ponieważ nie jest jeszcze określona:

>>> ins1.foo 
Traceback (most recent call last): 
    File "<ipython-input-62-9495b4da308f>", line 1, in <module> 
    ins1.foo 
AttributeError: Test1 instance has no attribute 'foo' 

>>> ins1.display(12) 
foo : 12 
>>> ins1.foo 
12 

Jeśli chcesz zainicjować niektóre atrybuty instancji, gdy instancja jest tworzona, a następnie umieścić je wewnątrz metody __init__ .

class A(object): 
    bar = 10 
    def __init__(self, foo): 
     self.foo = foo #this gets initialized when the instance is created 
    def func(self, x): 
     self.spam = x #this will be available only when you call func() on the instance 
...   
>>> a = A(10) 
>>> a.bar 
10 
>>> a.foo 
10 
>>> a.spam 
Traceback (most recent call last): 
    File "<ipython-input-85-3b4ed07da1b4>", line 1, in <module> 
    a.spam 
AttributeError: 'A' object has no attribute 'spam' 

>>> a.func(2) 
>>> a.spam 
2 
+1

Myślę, że główną różnicą jest to, że atrybut klasy jest "udostępniony", a nie że jest dostępny dla wszystkich instancji. – phant0m

1

Osobiście nie podoba definiowania zmiennych instancji wewnątrz metod innych niż __init__ lub jako zmienne klasy jak bar W przykładzie powyżej.

Jeszcze raz osobiście lubię widzieć każdego członka mojej klasy, patrząc na górę. Niezależnie od tego, czy jest to zmienna klasy, której używasz jako zmiennej instancji (coś, czego zazwyczaj nie robię), czy zmienna instancji zdefiniowana w __init__, łatwo jest określić, co jest i nie jest zdefiniowane w klasie, sprawdzając pierwszą sekcję definicji klasy.

Jeśli nie będziesz potrzebować dostępu do zmiennej jako członek klasy (tj. Będziesz ją tam definiować tylko w celu uniknięcia zapisu self.variable = val w metodzie __init__, to będę musiał omijać ją. to jako zmienną klasy, to robi to, co jesteś z bar jest ok w mojej książce.

byłby to mój ulubiony sposób pisania ci klasę.

class Test1: 

    def __init__(self): 
     self.foo = None 
     self.bar = 10 

    def display(self,foo): 
     self.foo=foo 
     print "foo : ",self.foo #80 

    def display1(self): 
     print "bar: ", self.bar #10 
     print "again foo: ", self.foo #80 
Powiązane problemy