Wie sagt Python "das heißt als Funktion"?

Ein kündbares Objekt soll also sein, indem man __call__ definiert. Eine Klasse soll ein Objekt sein … oder zumindest mit einigen Ausnahmen. Diese Ausnahme ist, was ich nicht formell klären kann, also ist diese Frage hier gepostet.

Sei A eine einfache Klasse:

 class A(object): def call(*args): return "In `call`" def __call__(*args): return "In `__call__`" 

Die erste Funktion wird absichtlich "call" genannt, um klar zu machen, dass der Zweck der Vergleich mit dem anderen ist.

Lassen Sie uns es instanziieren und vergessen Sie den Ausdruck, den es impliziert:

 a = A() # Think of it as `a = magic` and forget about `A()` 

Nun, was lohnt sich:

 print(A.call()) print(a.call()) print(A()) print(a()) 

Ergebnis in:

 >>> In `call` >>> In `call` >>> <__main__.A object at 0xNNNNNNNN> >>> In `__call__` 

Die Ausgabe (dritte Anweisung, die nicht __call__ läuft) ist nicht überraschend, aber wenn ich denke, woher es heißt "Python-Klasse sind Objekte" …

Dies, mehr explizit, aber laufen __call__

 print(A.__call__()) print(a.__call__()) >>> “In `__call__`” >>> “In `__call__`” 

All dies ist nur zu zeigen, wie endlich A() seltsam aussehen kann.

Es gibt Ausnahme in Python Regeln, aber die Dokumentation über "Objekt. Rufen Sie " sagt nicht viel über __call__ … nicht mehr als das:

3.3.5. Emulation kündbarer Gegenstände

 object.__call__(self[, args...]) 

Wird aufgerufen, wenn die Instanz als Funktion "aufgerufen" wird. […]

Aber wie sagt Python "es heißt eine Funktion" und Ehre oder nicht das object.__call__ rule?

Dies könnte eine Art von Typ sein, aber auch Typ hat object als seine Basisklasse.

Wo kann ich mehr (und formell) darüber erfahren?

Übrigens gibt es hier zwischen Python 2 und Python 3 keinen Unterschied?

—–% <—– edit —–>% —–

Schlussfolgerungen und andere Experimente nach einer Antwort und einem Kommentar

Update # 1

Nach @ Veedrac's Antwort und @ Chepner's Kommentar, kam ich zu diesem anderen Test, die die Kommentare von beiden:

 class M(type): def __call__(*args): return "In `M.__call__`" class A(object, metaclass=M): def call(*args): return "In `call`" def __call__(*args): return "In `A.__call__`" print(A()) 

Das Ergebnis ist:

 >>> In `M.__call__` 

So scheint es, dass ist die Meta-Klasse, die die "Call" Operationen fährt. Wenn ich es richtig verstehe, ist die Metaklasse nicht nur mit Klasse, sondern auch mit Klasseninstanzen wichtig.

Update # 2

Ein weiterer relevanter Test, der dies zeigt, ist kein Attribut des Objekts, das zählt, sondern ein Attribut der Art des Objekts:

 class A(object): def __call__(*args): return "In `A.__call__`" def call2(*args): return "In `call2`" a = A() print(a()) 

Wie erwartet, druckt es:

 >>> In `A.__call__` 

Jetzt das:

 a.__call__ = call2 print(a()) 

Es druckt:

 >>> In `A.__call__` 

Das gleiche a, bevor das Attribut zugewiesen wurde. Es wird nicht In call2 , es ist immer noch In A.__call__ . Das ist wichtig zu beachten und auch zu erklären, warum das ist die __call__ der Meta-Klasse, die aufgerufen wurde (denken Sie daran, die Meta-Klasse ist die Art des Klassenobjekts). Der __call__ wird als Funktion aufgerufen, ist nicht vom Objekt, sondern von seinem Typ.

One Solution collect form web for “Wie sagt Python "das heißt als Funktion"?”

x(*args, **kwargs) ist das gleiche wie type(x).__call__(x, *args, **kwargs) .

Also hast du

 >>> type(A).__call__(A) <__main__.A object at 0x7f4d88245b50> 

Und alles macht Sinn.


Chepner zeigt in den Kommentaren, dass type(A) == type . Das ist irgendwie wierd, denn type(A)(A) gibt einfach wieder type ! Aber denken Sie daran, dass wir stattdessen den type(A).__call__(A) der nicht der gleiche ist .

So löst sich der type.__call__(A) . Dies ist die Konstruktorfunktion für Klassen, die die Datenstrukturen aufbaut und die gesamte Baumagie macht.


Das gleiche gilt für die meisten dunder (doppelten Unterstrich) Methoden, wie __eq__ . Dies ist teilweise eine Optimierung in diesen Fällen.

Python ist die beste Programmiersprache der Welt.