Ich möchte den Zugriff auf eine Variable in einer Klasse überschreiben, aber alle anderen normal zurückgeben. Wie schaffe ich das mit __getattribute__
?
Ich habe Folgendes versucht (was auch veranschaulichen sollte, was ich versuche), aber ich erhalte einen Rekursionsfehler:
class D(object):
def __init__(self):
self.test=20
self.test2=21
def __getattribute__(self,name):
if name=='test':
return 0.
else:
return self.__dict__[name]
>>> print D().test
0.0
>>> print D().test2
...
RuntimeError: maximum recursion depth exceeded in cmp
super(D, self).__getattribute__(name)
super().__getattribute__(name)
in Python 3 verwenden.Eigentlich glaube ich, dass Sie
__getattr__
stattdessen die spezielle Methode verwenden möchten .Zitat aus den Python-Dokumenten:
Hinweis: Damit dies funktioniert, sollte die Instanz nicht ein haben
test
Attribut, so dass die Zeileself.test=20
sollte entfernt werden.quelle
__getattr__
fürtest
nutzlos, da es immer "an den üblichen Stellen" gefunden würde.Python-Sprachreferenz:
Bedeutung:
Sie fordern ein Attribut namens
__dict__
. Weil es ein Attribut ist,__getattribute__
wird es auf der Suche nach__dict__
den Anrufen__getattribute__
aufgerufen, die anrufen ... yada yada yadaDie Verwendung der Basisklassen
__getattribute__
hilft beim Auffinden des realen Attributs.quelle
Sind Sie sicher, dass Sie verwenden möchten
__getattribute__
? Was versuchst du eigentlich zu erreichen?Der einfachste Weg, das zu tun, was Sie verlangen, ist:
oder:
Bearbeiten: Beachten Sie, dass eine Instanz von
D
jeweils unterschiedliche Werte von haben würdetest
. Im ersten Falld.test
wäre es 20, im zweiten wäre es 0. Ich überlasse es Ihnen, herauszufinden, warum.Edit2: Greg wies darauf hin, dass Beispiel 2 fehlschlagen wird, da die Eigenschaft schreibgeschützt ist und die
__init__
Methode versucht hat, sie auf 20 zu setzen. Ein vollständigeres Beispiel dafür wäre:Natürlich ist dies als Klasse fast völlig nutzlos, aber es gibt Ihnen eine Idee, von der Sie weitermachen können.
quelle
Hier ist eine zuverlässigere Version:
Es ruft die Methode __ getattribute __ von der übergeordneten Klasse auf und greift schließlich auf das Objekt zurück. __ getattribute __ Methode, wenn andere Vorfahren sie nicht überschreiben.
quelle
Es wird vor der normalen gepunkteten Suche aufgerufen. Wenn es erhöht
AttributeError
, rufen wir an__getattr__
.Die Anwendung dieser Methode ist eher selten. In der Standardbibliothek gibt es nur zwei Definitionen:
Beste Übung
Der richtige Weg, um den Zugriff auf ein einzelnes Attribut programmgesteuert zu steuern, ist mit
property
. Die KlasseD
sollte wie folgt geschrieben werden (mit dem Setter und Deleter optional, um das offensichtliche beabsichtigte Verhalten zu replizieren):Und Verwendung:
Eine Eigenschaft ist ein Datendeskriptor, daher ist sie das erste, wonach im normalen Algorithmus für die gepunktete Suche gesucht wird.
Optionen für
__getattribute__
Sie haben mehrere Möglichkeiten, wenn Sie unbedingt die Suche für jedes Attribut über implementieren müssen
__getattribute__
.AttributeError
, wodurch__getattr__
aufgerufen wird (falls implementiert)super
, um die übergeordneteobject
Implementierung (wahrscheinlich ) aufzurufen__getattr__
Beispielsweise:
Was du ursprünglich wolltest.
Und dieses Beispiel zeigt, wie Sie das tun können, was Sie ursprünglich wollten:
Und wird sich so verhalten:
Code-Review
Ihr Code mit Kommentaren. Sie haben eine gepunktete Suche nach sich selbst in
__getattribute__
. Aus diesem Grund wird ein Rekursionsfehler angezeigt. Sie können überprüfen, ob der Name lautet,"__dict__"
und ihnsuper
zur Problemumgehung verwenden, dies gilt jedoch nicht__slots__
. Das überlasse ich dem Leser als Übung.quelle