Ich weiß, dass die __call__
Methode in einer Klasse ausgelöst wird, wenn die Instanz einer Klasse aufgerufen wird. Ich habe jedoch keine Ahnung, wann ich diese spezielle Methode verwenden kann, da man einfach eine neue Methode erstellen und dieselbe Operation ausführen kann, die in __call__
method ausgeführt wird, und anstatt die Instanz aufzurufen, können Sie die Methode aufrufen.
Ich würde es wirklich begrüßen, wenn mir jemand eine praktische Anwendung dieser speziellen Methode geben würde.
python
methods
call
magic-methods
mohi666
quelle
quelle
__call__
ist in der Übersicht verborgen. So instanziieren Sie eine Klasse: Istx = Foo()
wirklichx = type(Foo).__call__(Foo)
, wo__call__
durch die Metaklasse von definiert wirdFoo
.Antworten:
Das Django-Formularmodul verwendet eine
__call__
Methode, um eine konsistente API für die Formularvalidierung zu implementieren. Sie können Ihren eigenen Validator für ein Formular in Django als Funktion schreiben.Django verfügt über einige integrierte Standardvalidatoren wie E-Mail-Validatoren, URL-Validatoren usw., die weitgehend unter das Dach der RegEx-Validatoren fallen. Um diese sauber zu implementieren, greift Django auf aufrufbare Klassen (anstelle von Funktionen) zurück. Es implementiert die Standard-Regex-Validierungslogik in einem RegexValidator und erweitert diese Klassen dann für andere Validierungen.
Jetzt können sowohl Ihre benutzerdefinierte Funktion als auch der integrierte EmailValidator mit derselben Syntax aufgerufen werden.
Wie Sie sehen können, ähnelt diese Implementierung in Django dem, was andere in ihren Antworten unten erklärt haben. Kann dies auf andere Weise umgesetzt werden? Sie könnten, aber meiner Meinung nach wird es für ein großes Framework wie Django nicht so lesbar oder so leicht erweiterbar sein.
quelle
In diesem Beispiel wird die Memoisierung verwendet , wobei Werte im Grunde genommen in einer Tabelle (in diesem Fall im Wörterbuch) gespeichert werden, damit Sie sie später nachschlagen können, anstatt sie neu zu berechnen.
Hier verwenden wir eine einfache Klasse mit einer
__call__
Methode zur Berechnung von Fakultäten (über ein aufrufbares Objekt ) anstelle einer Fakultätsfunktion, die eine statische Variable enthält (da dies in Python nicht möglich ist).Jetzt haben Sie ein
fact
Objekt, das wie jede andere Funktion aufgerufen werden kann. BeispielsweiseUnd es ist auch zustandsbehaftet.
quelle
fact
indizierbares Objekt, da Ihre__call__
Funktion im Wesentlichen ein Index ist. Würde auch eine Liste anstelle eines Diktats verwenden, aber das bin nur ich.__call__
, einfach sein und nichts weiter.Ich finde es nützlich, weil ich damit APIs erstellen kann, die einfach zu verwenden sind (Sie haben ein aufrufbares Objekt, für das bestimmte Argumente erforderlich sind) und das einfach zu implementieren ist, weil Sie objektorientierte Methoden verwenden können.
Das Folgende ist Code, den ich gestern geschrieben habe und der eine Version der
hashlib.foo
Methoden erstellt, die ganze Dateien anstelle von Zeichenfolgen hashen:Diese Implementierung ermöglicht es mir, die Funktionen auf ähnliche Weise wie die
hashlib.foo
Funktionen zu verwenden:Natürlich hätte ich es anders implementieren können, aber in diesem Fall schien es ein einfacher Ansatz zu sein.
quelle
__call__
Sie ein Tool erhalten, mit dem Sie OO-Techniken verwenden können, um Probleme zu lösen.isinstance
ähnliche oder etwas.__call__
Methode anstelle eines Abschlusses verwenden möchten, ist das Multiprozessor-Modul, das mithilfe von Beizen Informationen zwischen Prozessen weitergibt. Sie können einen Abschluss nicht auswählen, aber Sie können eine Instanz einer Klasse auswählen.__call__
wird auch verwendet, um Dekorationsklassen in Python zu implementieren. In diesem Fall wird die Instanz der Klasse aufgerufen, wenn die Methode mit dem Dekorator aufgerufen wird.quelle
Ja, wenn Sie wissen, dass Sie mit Objekten arbeiten, ist es durchaus möglich (und in vielen Fällen ratsam), einen expliziten Methodenaufruf zu verwenden. Manchmal beschäftigen Sie sich jedoch mit Code, der aufrufbare Objekte erwartet - normalerweise Funktionen. Dank dieser Funktion
__call__
können Sie jedoch komplexere Objekte mit Instanzdaten und mehr Methoden zum Delegieren sich wiederholender Aufgaben usw. erstellen, die noch aufrufbar sind.Manchmal verwenden Sie auch sowohl Objekte für komplexe Aufgaben (wo es sinnvoll ist, eine dedizierte Klasse zu schreiben) als auch Objekte für einfache Aufgaben (die bereits in Funktionen vorhanden sind oder einfacher als Funktionen geschrieben werden können). Um eine gemeinsame Schnittstelle zu haben, müssen Sie entweder winzige Klassen schreiben, die diese Funktionen mit der erwarteten Schnittstelle umschließen, oder Sie behalten die Funktionsfunktionen bei und machen die komplexeren Objekte aufrufbar. Nehmen wir als Beispiel Threads. Die
Thread
Objekte aus dem Standard-Bibliotheksmodulthreading
möchten, dass eintarget
Argument als Argument aufgerufen werden kann (dh als Aktion, die im neuen Thread ausgeführt werden soll). Mit einem aufrufbaren Objekt sind Sie nicht auf Funktionen beschränkt, sondern können auch andere Objekte übergeben, z. B. einen relativ komplexen Worker, der Aufgaben von anderen Threads ausführt und diese nacheinander ausführt:Dies ist nur ein Beispiel aus meinem Kopf, aber ich denke, es ist bereits komplex genug, um die Klasse zu rechtfertigen. Dies nur mit Funktionen zu tun ist schwierig, zumindest müssen zwei Funktionen zurückgegeben werden, und das wird langsam komplex. Man könnte
__call__
in etwas anderes umbenennen und eine gebundene Methode übergeben, aber das macht den Code, der den Thread erstellt, etwas weniger offensichtlich und fügt keinen Wert hinzu.quelle
__call__
, dass Klasseninstanzen (anstelle von Funktionen) als WSGI-Anwendungen verwendet wurden. Hier ist ein Beispiel aus "The Definitive Guide to Pylons": Verwenden von Instanzen von KlassenKlassenbasierte Dekorateure
__call__
verweisen auf die umschlossene Funktion. Z.B:Eine gute Beschreibung der verschiedenen Optionen finden Sie hier bei Artima.com
quelle
IMHO-
__call__
Methode und -Verschlüsse bieten uns eine natürliche Möglichkeit, STRATEGIE-Entwurfsmuster in Python zu erstellen. Wir definieren eine Familie von Algorithmen, kapseln jeden, kapseln sie austauschbar und können am Ende eine Reihe gemeinsamer Schritte ausführen und beispielsweise einen Hash für eine Datei berechnen.quelle
Ich bin gerade auf eine Verwendung von
__call__()
im Konzert gestoßen, mit__getattr__()
der ich schön finde. Sie können mehrere Ebenen einer JSON / HTTP / (jedoch_serialisierten) API in einem Objekt ausblenden.Der
__getattr__()
Teil sorgt dafür, dass iterativ eine geänderte Instanz derselben Klasse zurückgegeben wird, wobei jeweils ein weiteres Attribut ausgefüllt wird. Nachdem alle Informationen erschöpft sind,__call__()
übernimmt er die von Ihnen eingegebenen Argumente.Mit diesem Modell können Sie beispielsweise einen Anruf wie tätigen
api.v2.volumes.ssd.update(size=20)
, der in einer PUT-Anfrage an endethttps://some.tld/api/v2/volumes/ssd/update
.Der jeweilige Code ist ein Blockspeichertreiber für ein bestimmtes Volume-Backend in OpenStack. Sie können ihn hier überprüfen: https://github.com/openstack/cinder/blob/master/cinder/volume/drivers/nexenta/jsonrpc.py
BEARBEITEN: Der Link wurde aktualisiert, um auf die Master-Revision zu verweisen.
quelle
Geben Sie a an
__metaclass__
und überschreiben Sie die__call__
Methode. Lassen Sie die Methode der angegebenen Metaklassen__new__
eine Instanz der Klasse zurückgeben. Viola, Sie haben eine "Funktion" mit Methoden.quelle
Wir können die
__call__
Methode verwenden, um andere Klassenmethoden als statische Methoden zu verwenden.quelle
Ein häufiges Beispiel ist das
__call__
Infunctools.partial
, hier ist eine vereinfachte Version (mit Python> = 3.5):Verwendung:
quelle
Der Funktionsaufrufoperator.
Die Methode __call__ kann verwendet werden, um dasselbe Objekt neu zu definieren / neu zu initialisieren. Es erleichtert auch die Verwendung von Instanzen / Objekten einer Klasse als Funktionen, indem Argumente an die Objekte übergeben werden.
quelle
Ich einen guten Platz finden aufrufbare Objekte zu verwenden, die , die definieren
__call__()
, ist , wenn die funktionalen Programmierfunktionen in Python, wiemap()
,filter()
,reduce()
.Die beste Zeit, um ein aufrufbares Objekt über eine einfache Funktion oder eine Lambda-Funktion zu verwenden, ist, wenn die Logik komplex ist und einen bestimmten Status beibehalten muss oder andere Informationen verwendet, die nicht an die
__call__()
Funktion übergeben wurden.Hier ist ein Code, der Dateinamen basierend auf ihrer Dateinamenerweiterung mithilfe eines aufrufbaren Objekts und filtert
filter()
.Abrufbar:
Verwendung:
Ausgabe:
quelle
Das ist zu spät, aber ich gebe ein Beispiel. Stellen Sie sich vor, Sie haben eine
Vector
Klasse und einePoint
Klasse. Beide nehmenx, y
als Positionsargumente. Stellen Sie sich vor, Sie möchten eine Funktion erstellen, die den Punkt verschiebt, der auf den Vektor gesetzt werden soll.4 Lösungen
put_point_on_vec(point, vec)
Machen Sie es zu einer Methode für die Vektorklasse. z.B
my_vec.put_point(point)
Point
Klasse.my_point.put_on_vec(vec)
Vector
implementiert__call__
, so können Sie es wie verwendenmy_vec_instance(point)
Dies ist tatsächlich Teil einiger Beispiele, an denen ich für einen Leitfaden für Dunder-Methoden arbeite, die mit Maths erklärt wurden und die ich früher oder später veröffentlichen werde.
Ich habe die Logik verlassen, den Punkt selbst zu verschieben, weil es nicht um diese Frage geht
quelle