übergeben - python__init__ erklärung




Warum verhalten sich Attributreferenzen bei Python-Vererbung so? (2)

Ich denke, der einfachste Weg, dies zu verstehen (damit Sie das Verhalten vorhersagen können), besteht darin zu erkennen, dass Ihre somedata ein Attribut der Klasse und nicht die Instanz dieser Klasse sind, wenn Sie sie so definieren.

Es gibt wirklich immer nur eine somedata weil Sie in Ihrem Beispiel diesen Namen nicht zugewiesen haben, sondern ihn verwendet haben, um ein dict nachzuschlagen und ihm dann ein Element (Schlüssel, Wert) zuzuweisen. Es ist ein Gotcha, das eine Folge davon ist, wie der Python-Interpreter funktioniert und zunächst verwirrend sein kann.

Das Folgende scheint seltsam. Grundsätzlich scheint das somedata-Attribut von allen Klassen gemeinsam genutzt zu werden, die von the_base_class geerbt the_base_class .

class the_base_class:
    somedata = {}
    somedata['was_false_in_base'] = False


class subclassthing(the_base_class):
    def __init__(self):
            print self.somedata


first = subclassthing()
{'was_false_in_base': False}
first.somedata['was_false_in_base'] = True
second = subclassthing()
{'was_false_in_base': True}
>>> del first
>>> del second
>>> third = subclassthing()
{'was_false_in_base': True}

Das Definieren von self.somedata in der __init__ Funktion ist offensichtlich der richtige Weg, dies zu somedata (also hat jede Klasse ihr eigenes somedata dict) - aber wann ist solch ein Verhalten wünschenswert?


Sie haben recht, somedata wird von allen Instanzen der Klasse und ihren Unterklassen gemeinsam genutzt, da sie zur Klassendefinitionszeit erstellt werden. Die Linien

somedata = {}
somedata['was_false_in_base'] = False

werden ausgeführt, wenn die Klasse definiert ist, dh wenn der Interpreter auf die class trifft - nicht, wenn die Instanz erstellt wird (denken Sie an statische Initialisierungsblöcke in Java). Wenn ein Attribut in einer Klasseninstanz nicht vorhanden ist, wird das Klassenobjekt auf das Attribut überprüft.

Zur Zeit der Klassendefinition können Sie Code wie folgt ausführen:

 import sys
 class Test(object):
     if sys.platform == "linux2":
         def hello(self):
              print "Hello Linux"
     else:
         def hello(self):
              print "Hello ~Linux"

Auf einem Linux-System wird mit Test().hello() Hello Linux gedruckt, auf allen anderen Systemen wird der andere String gedruckt.

Im __init__ werden Objekte in __init__ zur Instanziierungszeit erstellt und gehören nur zur Instanz (wenn sie sich selbst zugeordnet sind):

class Test(object):
    def __init__(self):
        self.inst_var = [1, 2, 3]

Objekte, die in einem Klassenobjekt anstelle einer Instanz definiert sind, können in vielen Fällen nützlich sein. Zum Beispiel könnten Sie Instanzen Ihrer Klasse zwischenspeichern, so dass Instanzen mit denselben Elementwerten freigegeben werden können (vorausgesetzt, sie sollen unveränderlich sein):

class SomeClass(object):
    __instances__ = {}

    def __new__(cls, v1, v2, v3):
        try:
            return cls.__insts__[(v1, v2, v3)]
        except KeyError:
            return cls.__insts__.setdefault(
               (v1, v2, v3), 
               object.__new__(cls, v1, v2, v3))

Meistens verwende ich Daten in Klassenkörpern in Verbindung mit Metaklassen oder generischen Factory-Methoden.





inheritance