Instanz der Python-Klasse, die auf alle Methodenaufrufe reagiert

8

Gibt es eine Möglichkeit, eine Klasse zu erstellen, die auf beliebige Methodenaufrufe reagiert?

Ich weiß, dass es eine spezielle Methode __getattr__(self, attr) gibt, die aufgerufen wird, wenn jemand versucht, auf ein Attribut einer Instanz zuzugreifen. Ich suche nach etwas ähnlichem, das es mir ermöglicht, auch Methodenaufrufe abzufangen. Das gewünschte Verhalten würde etwa so aussehen:

%Vor%

BEARBEITEN

Die anderen vorgeschlagenen Fragen behandeln meinen Fall nicht: Ich möchte keine andere Klasse umhüllen oder die Metaklasse einer zweiten Klasse oder ähnlichem ändern. Ich möchte nur eine Klasse haben, die auf beliebige Methodenaufrufe reagiert.

Dank jonrshape weiß ich jetzt, dass __getattr__(self, attr) auch aufgerufen wird, wenn eine Methode genau so aufgerufen wird wie beim Zugriff auf ein Attribut. Aber wie kann ich in __getattr__ unterscheiden, wenn attr von einem Methodenaufruf oder einem Attributzugriff kommt und wie man die Parameter eines möglichen Methodenaufrufs erhält?

    
Salo 14.10.2015, 12:32
quelle

3 Antworten

7

Das ist etwas, was ich herausgefunden habe, das sich genau so verhalten wird, als ob die Methode existiert.

Lassen Sie uns zunächst eines feststellen: Sie können nicht in __getattr__ unterscheiden, wenn attr von einem Funktionsaufruf oder einem "Attributzugriff" kommt, weil eine Klassenmethode ein Attribut Ihrer Klasse ist. So kann jemand auf diese Methode zugreifen, auch wenn sie nicht beabsichtigt, sie aufzurufen, wie in:

%Vor%

Daher ist das nächste, woran ich denken könnte, dieses Verhalten:

Erstellen Sie eine Klasse A, so dass:

  1. Wenn wir versuchen, auf ein Attribut / eine Methode zuzugreifen, das bereits in dieser Klasse existiert, verhalten Sie sich normal und geben nur das angeforderte Attribut / die Methode zurück.
  2. Wenn wir versuchen, auf etwas zuzugreifen, das in der Klassendefinition nicht existiert, behandeln wir es als Klassenmethode und haben einen globalen Handler für alle diese Methoden.

Ich schreibe zuerst die Klassendefinition und zeige dann, wie sich der Zugriff auf eine nicht existierende Methode genauso verhält wie der Zugriff auf eine existierende, ob man gerade darauf zugreift oder sie tatsächlich aufruft.

Klassendefinition:

%Vor%

Ich habe die Methode real_method nur hinzugefügt, damit ich etwas habe, das tatsächlich in der Klasse existiert, um ihr Verhalten mit dem einer 'imaginären Methode' zu vergleichen

Hier ist das Ergebnis:

%Vor%     
tomas 14.10.2015, 19:04
quelle
4

unittest.mock.Mock tut dies standardmäßig.

> %Vor%     
Adam Smith 14.10.2015 17:50
quelle
0

Methodenaufrufe unterscheiden sich nicht vom Zugriff auf Attribute. __getattr__() oder __getattribute__() ist die Möglichkeit, auf beliebige Attributanfragen zu antworten.

Sie können nicht wissen, ob der Zugriff von "nur Abruf" oder "Methodenaufruf" kommt.

Es funktioniert wie folgt: zuerst, attribute retrieval, rufen Sie dann das abgerufene Objekt (in Python, Anruf ist nur ein anderer Operator: alles kann aufgerufen werden und wird eine Ausnahme auslösen, wenn es nicht aufrufbar ist). Man kann und sollte nicht über den anderen Bescheid wissen (naja, man kann den Code auf dem Call-Stack analysieren, aber das ist hier absolut nicht der Fall).

Einer der Gründe ist - Funktionen sind erstklassige Objekte in Python, dh eine Funktion (oder besser gesagt eine Referenz darauf) unterscheidet sich nicht von anderen Datentypen: Ich kann die Referenz bekommen, speichern und übergeben es herum. I.e. Es besteht kein Unterschied zwischen der Anforderung eines Datenfelds und einer Methode.

Erarbeiten Sie, was Sie für uns brauchen, um eine bessere Lösung vorzuschlagen.

Wenn Sie z. B. die "Methode" benötigen, um mit verschiedenen Signaturen aufgerufen zu werden, ist *args und **kwargs der richtige Weg.

    
ivan_pozdeev 14.10.2015 16:04
quelle

Tags und Links