2016-07-31 18 views
0

Nach Python 2.7.12 Dokumentation:Wieso favorisieren Sie das Objekt .__ setattr __ (self, name, value) nur in neuen Stilklassen?

Wenn __setattr__() auf eine Instanz Attribut zuweisen will, sollte es nicht einfach self.name = value ausführen - dies eine rekursive Verbindung zu sich selbst führen würde. Stattdessen sollte es den Wert in das Verzeichnis von Instanzattributen einfügen, z. B. self.__dict__[name] = value. Für neuen Stil Klassen, anstatt die Instanz Wörterbuch zugreifen, es sollten die Basisklasse Methode mit dem gleichen Namen nennen, beispielsweise object.__setattr__(self, name, value).

jedoch der folgende Code funktioniert wie man erwarten würde:

class Class(object): 
    def __setattr__(self, name, val): 
     self.__dict__[name] = val; 

c = Class() 
c.val = 42 
print c.val 

Ich weiß super(Class, obj).__setattr__(name, value) die __setattr__ Methoden aller Basisklassen sicherzustellen, genannt zu werden, aber klassische Klasse kann auch von Basen Klassen erben. Warum wird es nur für neue Stilklassen empfohlen?

Oder auf der anderen Seite, warum ist dies nicht für klassische Klassen empfohlen?

+1

* Warum wird es nur für neue Stilklassen empfohlen? * Wenn man '__setattr__' aufruft, anstatt direkt im Instanzwörterbuch zu arbeiten, kann die Superklasse" überwachen ", was passiert. Stellen Sie sich diesen Ansatz als einen Vorteil neuer Stilklassen vor.Es wird wahrscheinlich für alle Klassen empfohlen, aber Klassen im alten Stil, die nicht erben, haben keine Superklasse mit einer aufrufbaren Methode "__setattr__". – jedwards

+1

@jedwards Yeah, da es für klassische Klassen kein 'classobj .__ setattr__' gibt, für neue style Klassen nur' object .__ setattr__'. –

+0

Sie sind genau richtig. Mein Punkt war, dass ich den fettgedruckten Satz sah, nicht so sehr wie die Entmutigung, das Instanz-Diktat direkt zu verwenden (wie Sie gezeigt haben, funktioniert es in vielen Fällen völlig einwandfrei, und wie Martijn gezeigt hat, gibt es Fälle, in denen dies nicht der Fall ist)), sondern eher eine Ermutigung *, um '__setattr__' zu verwenden, was der Oberklasse eine gewisse Übersicht und die Verwendung neuerer Merkmale wie Deskriptoren ermöglicht. Sorry, wenn ich unklar war :) – jedwards

Antwort

3

Klassen im neuen Stil könnten Steckplätze verwenden, zu diesem Zeitpunkt ist kein __dict__ zuzuweisen. Neue Stilklassen unterstützen auch andere Datendeskriptoren, Objekte, die in der Klasse definiert sind, die Attributeinstellungen für bestimmte Namen handhaben oder löschen.

Vom documentation on slots:

standardmäßig Instanzen der alten und neuen Stil Klassen haben einen Wörterbuch für Attributspeicher. Dies verschwendet Platz für Objekte mit sehr wenigen Instanzvariablen. Der Speicherplatzverbrauch kann akut werden, wenn eine große Anzahl von Instanzen erstellt wird.

Der Standardwert kann außer Kraft gesetzt werden, indem __slots__ in einer neuen Klassendefinition definiert wird. Die Deklaration __slots__ nimmt eine Sequenz von Instanzvariablen und reserviert gerade genug Speicherplatz in jeder Instanz, um einen Wert für jede Variable zu speichern. Speicherplatz wird gespeichert, da nicht für jede Instanz erstellt wird.

Der Zugriff auf Steckplätze wird stattdessen durch Hinzufügen von data descriptors auf die Klasse implementiert; ein Objekt mit __set__ und/oder __del__ Methoden für jedes solche Attribut.

Ein anderes Beispiel für Datendeskriptoren ist property() objects, an die eine Setter- oder Deleter-Funktion angeschlossen ist. Das Setzen eines Schlüssels mit dem gleichen Namen wie ein solches Deskriptor-Objekt in würde ignoriert werden, da Datendeskriptoren die Attributsuche dazu veranlassen, die __dict__ insgesamt zu umgehen.

object.__setattr__() weiß, wie man mit Datendeskriptoren umgeht, weshalb Sie das einfach anrufen sollten.

+0

Vielleicht "einen Schlüssel für ein solches Objekt in der '__dict__' würde ignoriert werden" sollte "Einstellung eines Schlüssels für ein Objekt, dessen Klasse verwendet Datendeskriptoren in der '__dict__' ignoriert werden" zu mach es klarer? –

+0

@sunqingyao: Das betreffende Objekt ist der Datendeskriptor für die Klasse. –

Verwandte Themen