2009-10-11 4 views
6

Was ist der Unterschied zwischenUnterschied zwischen der Definition eines Members in __init__, um es im Klassenhauptteil in Python zu definieren?

tun
class a: 
    def __init__(self): 
     self.val=1 

zu tun

class a: 
    val=1 
    def __init__(self): 
     pass 
+1

Duplizieren http://stackoverflow.com/questions/1537202/variables-inside-and-outside-of-a-class-init-function –

+2

Gleiche Frage innerhalb weniger Tage? Hausaufgaben? –

+0

Bitte werfen Sie einen Blick auf die anderen Fragen, die ich geschrieben habe, zum Beispiel: http://stackoverflow.com/questions/1547222/prevent-decorator-from-being-use-twice-on-the-same-function-in -python oder das: http: // stackoverflow.com/questions/1353173/ist-es-möglich-zu-a-flash-video-on-a-fogbugz-wiki-page (ich bezweifle, wie viele Schulen haben einen fogbugz account :)) auch, wenn es Jeder Ort, an dem du die IP des Nutzers sehen kannst - ich bin mir ziemlich sicher, dass der andere nicht aus dem gleichen Land wie ich ist. – olamundo

Antwort

10
class a: 
    def __init__(self): 
     self.val=1 

dies eine Klasse (in Py2 schafft, ein cruddy, Erbe, im alten Stil, das nicht tun, ! Klasse, in Py3 sind die fiesen alten Legacy-Klassen endlich weg, also wäre dies eine Klasse der einzigsten Art - die ** gute * Art, die in Py2 class a(object): erfordert), so dass jede Instanz mit anfängt es ist n Verweis auf das Integer-Objekt 1.

class a: 
    val=1 
    def __init__(self): 
     pass 

dies schafft eine Klasse (von derselben Art), die selbst eine Referenz auf das Objekt hat ganzzahlige 1 (Start seine Instanzen ohne pro Instanz Referenz out).

Für immutables wie int Werte, es ist schwer, einen praktischen Unterschied zu sehen. In beiden Fällen wird zum Beispiel in den folgenden Fällen self.val = 2 auf einer Instanz a eine Instanz Verweis (die vorhandene Antwort ist in dieser Hinsicht falsch falsch).

Die Unterscheidung ist wichtig für veränderbare Objekte, weil sie Mutator-Methoden haben, so ist es ziemlich wichtig zu wissen, ob eine bestimmte Liste pro Instanz eindeutig oder unter allen Instanzen geteilt ist. Aber für unveränderliche Objekte, da Sie nie das Objekt selbst ändern können, aber nur zuweisen (z. B. zu self.val, die immer eine pro-Instanz-Verweis wird), ist es ziemlich gering.

Gerade über den einzigen relevanten Unterschied für immutables: Wenn Sie später a.val = 3 zuweisen, im ersten Fall wird dies beeinflussen, was jeweils als self.val gesehen hat (mit Ausnahme von Fällen, die ihre eigenen self.valzugewiesen mußten oder gleichwertige Maßnahmen); Im zweiten Fall hat dies keinen Einfluss darauf, was von einer Instanz als self.val angesehen wird (außer für Instanzen, für die Sie del self.val oder entsprechende Aktionen ausgeführt haben).

5

Wie von anderen erwähnt, ist es in einem Fall ein Attribut für die Klasse und ein Attribut für die Instanz. Ist das wichtig? Ja, in einem Fall. Wie Alex sagte, wenn der Wert veränderbar ist. Die beste Erklärung ist Code, also füge ich etwas Code hinzu, um es zu zeigen (das ist alles, was diese Antwort wirklich tut):

Zuerst eine Klasse, die zwei Instanzattribute definiert.

>>> class A(object): 
...  def __init__(self): 
...   self.number = 45 
...   self.letters = ['a', 'b', 'c'] 
... 

Und dann eine Klasse, die zwei Klassenattribute definiert.Jetzt

>>> class B(object): 
...  number = 45 
...  letters = ['a', 'b', 'c'] 
... 

wir sie verwenden:

>>> a1 = A() 
>>> a2 = A() 
>>> a2.number = 15 
>>> a2.letters.append('z') 

Und alles ist gut:

>>> a1.number 
45 
>>> a1.letters 
['a', 'b', 'c'] 

nun die Klassenattribut Variation verwenden:

>>> b1 = B() 
>>> b2 = B() 
>>> b2.number = 15 
>>> b2.letters.append('z') 

und alles ist .. .well ...

>>> b1.number 
45 
>>> b1.letters 
['a', 'b', 'c', 'z'] 

Ja, beachten Sie, dass das veränderbare Klassenattribut bei der Änderung für alle Klassen geändert wurde. Das ist normalerweise nicht das, was du willst.

Wenn Sie das ZODB verwenden, verwenden Sie viele Klassenattribute, da es eine praktische Möglichkeit ist, vorhandene Objekte mit neuen Attributen zu aktualisieren oder Informationen auf Klassenebene hinzuzufügen, die nicht persistent sind. Ansonsten können Sie sie ziemlich ignorieren.

6

Andere haben die technischen Unterschiede erklärt. Ich werde versuchen zu erklären, warum Sie möglicherweise Klassenvariablen verwenden möchten.

Wenn Sie die Klasse nur einmal instanziieren, sind Klassenvariablen Instanzvariablen. Wenn Sie jedoch viele Kopien erstellen oder den Status für einige Instanzen freigeben möchten, sind Klassenvariablen sehr hilfreich. Zum Beispiel:

class Foo(object): 
    def __init__(self): 
     self.bar = expensivefunction() 

myobjs = [Foo() for _ in range(1000000)] 

wird teurefunction() millionenfach aufgerufen werden. Wenn Sie jedes Mal denselben Wert zurückgeben möchten, z. B. das Abrufen eines Konfigurationsparameters aus einer Datenbank, sollten Sie überlegen, sie in die Klassendefinition zu verschieben, sodass sie nur einmal aufgerufen und dann für alle Instanzen freigegeben wird.

Ich verwende auch Klassenvariablen sehr oft beim Memoizing von Ergebnissen. Beispiel:

class Foo(object): 
    bazcache = {} 

    @classmethod 
    def baz(cls, key): 
     try: 
      result = cls.bazcache[key] 
     except KeyError: 
      result = expensivefunction(key) 
      cls.bazcache[key] = result 
     return result 

In diesem Fall ist Baz eine Klassenmethode; Das Ergebnis hängt nicht von Instanzvariablen ab. Das bedeutet, dass wir eine Kopie des Ergebniscaches in der Klassenvariablen aufbewahren können, sodass 1) Sie nicht dieselben Ergebnisse mehrfach speichern und 2) jede Instanz von Ergebnissen profitieren kann, die von anderen Instanzen zwischengespeichert wurden.

Angenommen, Sie haben eine Million Instanzen, die jeweils auf den Ergebnissen einer Google-Suche basieren. Sie würden wahrscheinlich bevorzugen, dass all diese Objekte diese Ergebnisse teilen, als dass jeder die Suche ausführt und auf die Antwort wartet.

Also würde ich Lennart hier nicht zustimmen. Klassenvariablen sind sehr in bestimmten Fällen bequem. Wenn sie das richtige Werkzeug für den Job sind, zögern Sie nicht, sie zu verwenden.

Verwandte Themen