Intercepting Änderungen von Attributen in Klassen innerhalb einer Klasse - Python
-
21-08-2019 - |
Frage
Ich habe mit pygame und Python rumgespielt und ich möchte in der Lage sein, eine Funktion aufzurufen, wenn ein Attribut meiner Klasse geändert hat. Meine aktuelle Lösung Wesen:
class ExampleClass(parentClass):
def __init__(self):
self.rect = pygame.rect.Rect(0,0,100,100)
def __setattr__(self, name, value):
parentClass.__setattr__(self,name,value)
dofancystuff()
Firstclass = ExampleClass()
Das funktioniert gut und dofancystuff aufgerufen wird, wenn ich den rect Wert mit Firsclass.rect = pygame.rect.Rect(0,0,100,100)
ändern. Allerdings, wenn ich sage, Firstclass.rect.bottom = 3
. __setattr__
und dort für dofancystuff nicht aufgerufen wird.
Also meine Frage, die ich denke, ist, wie kann ich abfangen jede Änderung an einem Attribut einer Unterklasse?
edit: Auch wenn ich über das der falsche Weg, bitte werde ich sagen, ich bin nicht sehr kenntnisreich, wenn es um Python kommt
.Lösung
Nun, die einfache Antwort ist, kann man nicht. Im Fall von Firstclass.rect = <...>
ist Ihr __setattr__
genannt. Aber im Fall von Firstclass.rect.bottom = 3
die __setattr__
Methode der Rect-Instanz aufgerufen wird. Die einzige Lösung, die ich sehe, ist eine abgeleitete Klasse von pygame.rect.Rect zu schaffen, in dem Sie die __setattr__
Methode überschreiben. Sie können auch die Rect Klasse Affe Patch, aber dies ist aus guten Gründen abgeraten.
Andere Tipps
Sie könnten versuchen, __getattr__
, die auf Firstclass.rect
aufgerufen werden soll.
Aber tun Sie stattdessen: Erstellen Sie eine separate Klasse (Unterklasse von pygame.rect
?) Für ExampleClass.rect
. Implementieren __setattr__
in dieser Klasse. Nun werden Sie über alles gesagt, dass für rect
in Ihrem ExampleClass
Mitglied gesetzt wird. Sie können immer noch __setattr__
in ExampleClass
implementieren (und sollte ), erst jetzt stellen Sie sicher, eine Version Ihrer eigenen rect
Klasse instanziiert ...
BTW: Rufen Sie nicht Ihre Objekte Firstclass
, wie dann sieht es aus wie eine Klasse, die als Gegensatz zu einem Objekt ...
Das ist die Frage nicht beantworten, aber es ist relevant:
self.__dict__[name] = value
ist wahrscheinlich besser als
parentClass.__setattr__(self, name, value)
Dies wird durch die Python-Dokumentation empfohlen (setattr "> http://docs.python.org/2/reference/datamodel.html?highlight=setattr#object. setattr ) und macht mehr Sinn ohnehin im allgemeinen Fall, da sie davon ausgehen, nichts über das Verhalten von Parent setattr .
Yay für ungebetene Ratschläge 4 Jahre zu spät!
Ich denke, der Grund, warum Sie diese Schwierigkeiten haben, ein wenig mehr Informationen verdient, als von den anderen Antworten zur Verfügung gestellt wird.
Das Problem ist, wenn Sie das tun:
myObject.attribute.thing = value
Sie Zuordnung keinen Wert zuzuschreiben. Der Code entspricht dies:
anAttribute = myObject.attribute
anAttribute.thing = value
Wie es von myObject gesehen hat, alles, was Sie tun es das Attribut bekommen; Sie sind nicht das Attribut festlegen.
Erstellen Subklassen Ihrer Attribute, die Sie steuern und definieren __setattr__ kann für eine Lösung ist.
Eine alternative Lösung, die Sinn machen, wenn Sie viele Attribute verschiedener Typen haben und wollen nicht viele einzelne Unterklassen für alle von ihnen machen, ist __getattribute__ oder __getattr__ außer Kraft zu setzen eine Fassade auf das Attribut zurückzuversetzen führt die entsprechenden Operationen in seiner __setattr__ Methode. Ich habe nicht zu tun dies selbst versucht, aber ich kann mir vorstellen, dass Sie in der Lage sein sollte, eine einfache Fassade Klasse zu machen, die für jedes Objekt als Fassade dienen soll.
Pflege müssten bei der Wahl der __getattribute__ und __getattr__ . Siehe die im vorhergehenden Satz verknüpft Dokumentation für Informationen, aber im Grunde, wenn __getattr__ verwendet wird, haben die aktuellen Attribute oben gekapselt sein / verschleierten irgendwie so dass __getattr__ Anfragen für sie behandelt, und wenn __getattribute__ verwendet wird, wird es haben Attribute abrufen über Anrufe an eine Basisklasse.
Wenn alle Sie versuchen zu tun, ist festzustellen, ob einige Rects aktualisiert wurden, dann ist dies viel des Guten.