Ich versuche den Unterschied zu verstehen __getattr__
und __getattribute__
versage es jedoch.
Die Antwort auf die Frage zum Stapelüberlauf Der Unterschied zwischen __getattr__
vs__getattribute__
lautet:
__getattribute__
wird aufgerufen, bevor die tatsächlichen Attribute des Objekts angezeigt werden, und kann daher schwierig zu implementieren sein. Sie können sehr leicht in unendliche Rekursionen geraten.
Ich habe absolut keine Ahnung, was das bedeutet.
Dann heißt es weiter:
Sie wollen mit ziemlicher Sicherheit
__getattr__
.
Warum?
Ich habe gelesen, dass wenn __getattribute__
fehlschlägt, __getattr__
aufgerufen wird. Warum gibt es zwei verschiedene Methoden, die dasselbe tun? Was soll ich verwenden, wenn mein Code die neuen Stilklassen implementiert?
Ich suche nach Codebeispielen, um diese Frage zu klären. Ich habe nach besten Kräften gegoogelt, aber die Antworten, die ich gefunden habe, diskutieren das Problem nicht gründlich.
Wenn es Unterlagen gibt, bin ich bereit, diese zu lesen.
quelle
Antworten:
Einige Grundlagen zuerst.
Bei Objekten müssen Sie sich mit ihren Attributen befassen. Normalerweise tun wir das
instance.attribute
. Manchmal brauchen wir mehr Kontrolle (wenn wir den Namen des Attributs nicht im Voraus kennen).Zum Beispiel
instance.attribute
würde werdengetattr(instance, attribute_name)
. Mit diesem Modell können wir das Attribut erhalten, indem wir den Attributnamen als Zeichenfolge angeben.Gebrauch von
__getattr__
Sie können einer Klasse auch mitteilen, wie sie mit Attributen umgehen soll, die sie nicht explizit verwaltet, und dies über eine
__getattr__
Methode tun .Python ruft diese Methode immer dann auf, wenn Sie ein Attribut anfordern, das noch nicht definiert wurde, damit Sie definieren können, was damit geschehen soll.
Ein klassischer Anwendungsfall:
Vorsichtsmaßnahmen und Verwendung von
__getattribute__
Wenn Sie jedes Attribut abfangen müssen, unabhängig davon, ob es vorhanden ist oder nicht , verwenden Sie
__getattribute__
stattdessen. Der Unterschied besteht darin, dass__getattr__
nur Attribute aufgerufen werden, die tatsächlich nicht vorhanden sind. Wenn Sie ein Attribut direkt festlegen, wird es durch Verweisen auf dieses Attribut abgerufen, ohne es aufzurufen__getattr__
.__getattribute__
wird immer aufgerufen.quelle
getattr(instance, attribute_name)
." Sollte es nicht sein__getattribute__(instance, attribute_name)
?getattr
ist eine integrierte Funktion.getattr(foo, 'bar')
ist äquivalent zufoo.bar
.__getattr__
nur aufgerufen wird, wenn es definiert ist, da es nicht vonobject
__getattribute__
wird aufgerufen, wenn ein Attributzugriff erfolgt.Dies führt zu einer unendlichen Rekursion. Der Schuldige hier ist die Linie
return self.__dict__[attr]
. Stellen wir uns vor (es ist nah genug an der Wahrheit), dass alle Attribute inself.__dict__
ihrem Namen gespeichert sind und unter diesem Namen verfügbar sind. Die Linieversucht, auf das
a
Attribut von zuzugreifenf
. Dies ruft auff.__getattribute__('a')
.__getattribute__
versucht dann zu ladenself.__dict__
.__dict__
ist ein Attribut vonself == f
und so Python-Aufrufe,f.__getattribute__('__dict__')
die erneut versuchen, auf das Attribut zuzugreifen'__dict__
'. Dies ist eine unendliche Rekursion.Wenn
__getattr__
stattdessen verwendet worden wäref
es eina
Attribut hat.f.b
), wäre es nicht zum Suchen aufgerufen worden,__dict__
da es bereits vorhanden ist und__getattr__
nur aufgerufen wird, wenn alle anderen Methoden zum Suchen des Attributs fehlgeschlagen sind .Die 'richtige' Art, die obige Klasse mit zu schreiben,
__getattribute__
istsuper(Foo, self).__getattribute__(attr)
bindet die__getattribute__
Methode der 'nächsten' Oberklasse (formal die nächste Klasse in der Method Resolution Order oder MRO der Klasse) an das aktuelle Objektself
und ruft sie dann auf und lässt dies die Arbeit erledigen.All diese Probleme werden vermieden, indem
__getattr__
Python so lange ausgeführt wird, bis ein Attribut nicht gefunden wird. An diesem Punkt übergibt Python die Kontrolle an Ihre__getattr__
Methode und lässt sie sich etwas einfallen lassen.Es ist auch erwähnenswert, dass Sie mit in eine unendliche Rekursion geraten können
__getattr__
.Ich werde das als Übung belassen.
quelle
Ich denke, die anderen Antworten haben den Unterschied zwischen
__getattr__
und hervorragend erklärt__getattribute__
, aber eine Sache, die möglicherweise nicht klar ist, ist, warum Sie sie verwenden möchten__getattribute__
. Das Coole daran__getattribute__
ist, dass Sie den Punkt beim Zugriff auf eine Klasse im Wesentlichen überladen können. Auf diese Weise können Sie anpassen, wie auf Attribute auf niedriger Ebene zugegriffen wird. Angenommen, ich möchte eine Klasse definieren, in der alle Methoden, die nur ein Selbstargument verwenden, als Eigenschaften behandelt werden:Und vom interaktiven Dolmetscher:
Natürlich ist dies ein dummes Beispiel und Sie würden dies wahrscheinlich nie tun wollen, aber es zeigt Ihnen die Kraft, die Sie durch Überschreiben erhalten können
__getattribute__
.quelle
Ich habe die ausgezeichnete Erklärung anderer durchgesehen. Ich fand jedoch eine einfache Antwort von diesem Blog Python Magic Methods und
__getattr__
. Alle folgenden sind von dort.Mit der
__getattr__
magischen Methode können wir diese nicht vorhandene Attributsuche abfangen und etwas tun, damit es nicht fehlschlägt:Wenn das Attribut jedoch vorhanden ist,
__getattr__
wird es nicht aufgerufen:__getattribute__
ist ähnlich wie__getattr__
, mit dem wichtigen Unterschied,__getattribute__
der JEDE Attributsuche abfängt , spielt es keine Rolle, ob das Attribut existiert oder nicht.In diesem Beispiel hat das
d
Objekt bereits einen Attributwert. Wenn wir jedoch versuchen, darauf zuzugreifen, erhalten wir nicht den ursprünglich erwarteten Wert („Python“). Wir bekommen nur alles__getattribute__
zurück. Dies bedeutet, dass wir das Wertattribut praktisch verloren haben. es ist „unerreichbar“ geworden.quelle