Ich habe eine Variable x
und möchte wissen, ob sie auf eine Funktion zeigt oder nicht.
Ich hatte gehofft, ich könnte so etwas tun:
>>> isinstance(x, function)
Aber das gibt mir:
Traceback (most recent call last):
File "<stdin>", line 1, in ?
NameError: name 'function' is not defined
Der Grund, warum ich das ausgewählt habe, ist, weil
>>> type(x)
<type 'function'>
insepct.getsource
für eine Vielzahl von Objekten verwenden wollte, und es ist eigentlich nicht wichtig, ob das Objekt aufrufbar ist, sondern ob es etwas ist, für das 'Funktion' gegeben isttype(obj)
. Da Google mich hierher geführt hat, würde ich sagen, dass der Kommentar von AsTeR (für mich) die nützlichste Antwort war. Es gibt viele andere Orte im Internet, die Menschen entdecken__call__
oder entdecken könnencallable
.Antworten:
Wenn dies für Python 2.x oder Python 3.2+ ist, können Sie auch verwenden
callable()
. Früher war es veraltet, jetzt ist es nicht mehr veraltet, sodass Sie es wieder verwenden können. Sie können die Diskussion hier lesen: http://bugs.python.org/issue10518 . Sie können dies tun mit:Wenn dies für Python 3.x, jedoch vor 3.2 gilt, überprüfen Sie, ob das Objekt ein
__call__
Attribut hat. Sie können dies tun mit:Der oft vorgeschlagene
types.FunctionTypes
Ansatz ist nicht korrekt, da er viele Fälle nicht abdeckt, von denen Sie vermutlich möchten, dass er erfolgreich ist, wie bei integrierten Funktionen:Der richtige Weg, um die Eigenschaften von Objekten vom Typ Ente zu überprüfen, besteht darin, sie zu fragen, ob sie quaken, und nicht, ob sie in einen Behälter in Entengröße passen. Verwenden
types.FunctionType
Sie es nur, wenn Sie eine ganz bestimmte Vorstellung davon haben, was eine Funktion ist.quelle
Im Modul befinden sich integrierte Typen, die keine Konstruktoren im integrierten Namespace haben (z. B. Funktionen, Generatoren, Methoden)
types
. Sie könnentypes.FunctionType
in einemisinstance
Anruf verwenden:Beachten Sie, dass hierfür ein sehr spezifischer Begriff von "Funktion" verwendet wird, der normalerweise nicht Ihren Anforderungen entspricht. Zum Beispiel lehnt es ab
zip
(technisch gesehen eine Klasse):open
(Eingebaute Funktionen haben einen anderen Typ):und
random.shuffle
(technisch eine Methode einer verstecktenrandom.Random
Instanz):Wenn Sie etwas Spezifisches für
types.FunctionType
Instanzen tun, z. B. den Bytecode dekompilieren oder Abschlussvariablen untersuchen, verwenden Sietypes.FunctionType
, aber wenn Sie nur ein Objekt benötigen, das wie eine Funktion aufgerufen werden kann, verwenden Siecallable
.quelle
isinstance(f, (types.FunctionType, types.BuiltinFunctionType, functools.partial))
oderf.func
in einem solchen Fall.@foo
, den ich sowohl als@foo
als auch als verwenden kann@foo(some_parameter)
. Es muss dann überprüfen, mit was es aufgerufen wird, z. B. die zu dekorierende Funktion (erster Fall) oder der Parameter (der zweite Fall, in dem ein weiterer Dekorator zurückgegeben werden muss).types.BuiltinFunctionType
ist auch die Art der ("normalen") integrierten Methoden , die Sie wahrscheinlich nicht zulassen möchten, wenn Sie nicht diecallable
Route gehen.Seit Python 2.1 können Sie
isfunction
aus deminspect
Modul importieren .quelle
open
und zurückzugebenhasattr
.inspect.isfunction
Dokumentzeichenfolge: "Die akzeptierte Antwort wurde zu dem Zeitpunkt, als sie angeboten wurde, für richtig gehalten. Wie sich herausstellt, gibt es keinen Ersatz für
callable()
Python 3.2:callable()
Überprüft insbesondere dastp_call
Feld des zu testenden Objekts. Es gibt kein einfaches Python-Äquivalent. Die meisten der vorgeschlagenen Tests sind meistens korrekt:Wir können einen Schraubenschlüssel hineinwerfen, indem wir den
__call__
aus der Klasse entfernen . Und nur um die Dinge besonders aufregend zu halten, fügen Sie__call__
der Instanz eine Fälschung hinzu !Beachten Sie, dass dies wirklich nicht aufrufbar ist:
callable()
gibt das richtige Ergebnis zurück:Ist
hasattr
aber falsch :can_o_spam
hat dieses Attribut doch; Es wird beim Aufrufen der Instanz einfach nicht verwendet.Noch subtiler, versteht das
isinstance()
auch falsch:Da wir diese Prüfung früher und später verwendet haben, wurde die Methode
abc.ABCMeta
zwischengespeichert. Das ist wohl ein Fehlerabc.ABCMeta
. Das heißt, es ist wirklich keine Möglichkeit, es könnte ein genaueres Ergebnis als das Ergebnis produzieren , als durch den Einsatzcallable()
selbst, da dietypeobject->tp_call
Schlitzverfahren nicht zugänglich in irgendeiner anderen Art und Weise ist.Benutz einfach
callable()
quelle
hasattr(o, '__call__')
Ansatzes und warumcallable()
, falls verfügbar, überlegen ist.Folgendes sollte einen Booleschen Wert zurückgeben:
quelle
Das 2to3-Tool von Python ( http://docs.python.org/dev/library/2to3.html ) schlägt vor:
Es scheint, dass dies
hasattr(x, '__call__')
aufgrund von http://bugs.python.org/issue7006 anstelle der Methode gewählt wurde .quelle
callable()
Zurückbringen für py3.3 erwähnt: bugs.python.org/issue10518#msg122309callable(x)
wird true zurückgeben, wenn das übergebene Objekt in Python aufgerufen werden kann, die Funktion in Python 3.0 jedoch nicht vorhanden ist und im eigentlichen Sinne nicht zwischen folgenden Elementen unterschieden wird:Sie erhalten
<class 'A'> True
und<type function> True
als Ausgabe.isinstance
funktioniert perfekt, um festzustellen, ob etwas eine Funktion ist (versuchenisinstance(b, types.FunctionType)
); Wenn Sie wirklich daran interessiert sind, ob etwas aufgerufen werden kann, können Sie es entweder verwendenhasattr(b, '__call__')
oder einfach ausprobieren.Dies sagt Ihnen natürlich nicht, ob es aufrufbar ist, sondern wirft ein,
TypeError
wenn es ausgeführt wird, oder ist überhaupt nicht aufrufbar. Das ist dir vielleicht egal.quelle
Wenn Sie alles erkennen möchten, was syntaktisch wie eine Funktion aussieht: eine Funktion, eine Methode, ein integriertes fun / meth, ein Lambda ..., aber aufrufbare Objekte (Objekte mit definierter Methode) ausschließen möchten
__call__
, versuchen Sie Folgendes:Ich habe dies mit dem Code der
is*()
Prüfungen iminspect
Modul verglichen und der obige Ausdruck ist viel vollständiger, insbesondere wenn Ihr Ziel darin besteht, Funktionen herauszufiltern oder reguläre Eigenschaften eines Objekts zu erkennen.quelle
types
Modul hingewiesen haben . Ich habe einemake_stemmer()
Factory getestet , die manchmal eine Funktion und manchmal eine aufrufbareStemmer
Instanz zurückgibt , und ich musste den Unterschied erkennen.Versuchen Sie es mit
callable(x)
.quelle
Wenn Sie gelernt haben
C++
, müssen Sie mitfunction object
oder vertraut sein, dh mitfunctor
jedem Objekt, das dies kannbe called as if it is a function
.Ist in C ++
an ordinary function
ein Funktionsobjekt und ein Funktionszeiger. Im Allgemeinen ist dies auch ein Objekt einer Klasse, die definiertoperator()
. In C ++ 11 und höherthe lambda expression
ist dasfunctor
auch.Ähnlichkeit, in Python
functors
sind das allescallable
.An ordinary function
kann aufrufbar sein,a lambda expression
kann aufrufbar sein,functional.partial
kann aufrufbar sein, die Instanzen vonclass with a __call__() method
können aufrufbar sein.Ok, gehe zurück zu Frage:
I have a variable, x, and I want to know whether it is pointing to a function or not.
Dann mache ich ein Experiment mit diesem Code:
Ich zeichne eine Tabelle mit aufrufbaren Funktortypen unter Verwendung der Daten.
sowie:
quelle
Als akzeptierte Antwort erklärte John Feminella:
Obwohl es zwei Bibliotheken gibt, um Funktionen streng zu unterscheiden, zeichne ich eine erschöpfende vergleichbare Tabelle:
8.9. Typen - Dynamische Typerstellung und Namen für integrierte Typen - Python 3.7.0-Dokumentation
30.13. inspizieren - Live-Objekte untersuchen - Python 3.7.0-Dokumentation
Die "Ententypisierung" ist eine bevorzugte Lösung für allgemeine Zwecke:
Wie für die eingebaute Funktion
Wenn Sie noch einen Schritt weiter gehen, um zu überprüfen, ob die Funktion oder die benutzerdefinierte Funktion integriert ist
Bestimmen Sie, ob
builtin function
Zusammenfassung
Verwenden Sie, um den
callable
Typ zu überprüfen und eine Funktion zu überprüfen.Verwenden
types.BuiltinFunctionType
Sie diese Option , wenn Sie einen weiteren Bedarf angegeben haben.quelle
Eine Funktion ist nur eine Klasse mit einer
__call__
Methode, also können Sie dies tunZum Beispiel:
Das ist die "beste" Methode, aber je nachdem, warum Sie wissen müssen, ob es aufrufbar oder notierbar ist, können Sie es einfach in einen try / execpt-Block einfügen:
Es ist fraglich, ob try / exception mehr Python ist als zu tun
if hasattr(x, '__call__'): x()
. Ich würde sagen, eshasattr
ist genauer, da Sie nicht versehentlich den falschen TypeError abfangen, zum Beispiel:quelle
Hier sind einige andere Möglichkeiten:
So kam ich zum zweiten:
quelle
Statt zu prüfen
'__call__'
(die Funktionen nicht exklusiv ist), können Sie prüfen , ob eine benutzerdefinierte Funktion Attributefunc_name
,func_doc
etc. Das funktioniert nicht für Methoden.Eine andere Möglichkeit zur Überprüfung ist die Verwendung der
isfunction()
Methode aus deminspect
Modul.Verwenden Sie, um zu überprüfen, ob ein Objekt eine Methode ist
inspect.ismethod()
quelle
Da Klassen auch
__call__
Methoden haben, empfehle ich eine andere Lösung:quelle
hasattr(obj, '__call__')
ist mehrdeutig.Beachten Sie, dass Python-Klassen auch aufgerufen werden können.
Um Funktionen zu erhalten (und mit Funktionen meinen wir Standardfunktionen und Lambdas), verwenden Sie:
quelle
Welche Funktion auch immer eine Klasse ist, Sie können den Namen der Klasse der Instanz x nehmen und vergleichen:
quelle
Die Lösungen, die in einigen Antworten verwendet
hasattr(obj, '__call__')
undcallable(.)
erwähnt werden, haben einen Hauptnachteil: Beide geben auchTrue
für Klassen und Instanzen von Klassen mit einer__call__()
Methode zurück. Z.B.Eine geeignete Methode, um zu überprüfen, ob ein Objekt eine benutzerdefinierte Funktion ist (und nichts anderes als das), ist die Verwendung von
isfunction(.)
:Wenn Sie nach anderen Typen suchen müssen, schauen Sie unter inspizieren - Live-Objekte untersuchen nach .
quelle
Eine genaue Funktionsprüfung
Callable ist eine sehr gute Lösung. Ich wollte dies jedoch anders behandeln als John Feminella. Anstatt es wie folgt zu behandeln:
Wir werden es so behandeln:
Wie würden wir es umsetzen?
Das Modul 'types' verfügt über zahlreiche Klassen zum Erkennen von Funktionen. Die nützlichsten sind types.FunctionType . Es gibt jedoch auch viele andere Klassen , z. B. einen Methodentyp, einen integrierten Typ und einen Lambda-Typ. Wir werden auch ein 'functools.partial'-Objekt als eine Funktion betrachten.
Die einfache Möglichkeit, zu überprüfen, ob es sich um eine Funktion handelt, besteht darin, für alle diese Typen eine isinstance-Bedingung zu verwenden. Früher wollte ich eine Basisklasse erstellen, die von allen oben genannten Klassen erbt, aber das kann ich nicht, da Python es uns nicht erlaubt, von einigen der oben genannten Klassen zu erben.
Hier ist eine Tabelle, welche Klassen welche Funktionen klassifizieren können:
Über der Funktionstabelle von kinght- 金
Der Code, der es tut
Dies ist der Code, der alle oben beschriebenen Arbeiten ausführt.
Der einzige Fehler war is_function (teilweise), da dies eine Klasse ist, keine Funktion, und dies sind genau Funktionen, keine Klassen. Hier ist eine Vorschau, aus der Sie den Code ausprobieren können.
Fazit
callable (obj) ist die bevorzugte Methode, um zu überprüfen, ob ein Objekt eine Funktion ist, wenn Sie Enten über Absolutes tippen möchten .
Unsere kundenspezifischen is_function (obj) , vielleicht mit einigen Änderungen ist die bevorzugte Methode zu überprüfen , ob ein Objekt eine Funktion ist , wenn Sie nicht aufrufbar Klasseninstanz als Funktion zählen, sondern nur Funktionen definierten integrieren in oder mit Lambda , def oder teilweise .
Und ich denke, das fasst alles zusammen. Haben Sie einen guten Tag!
quelle
In Python3 habe ich mir ausgedacht,
type (f) == type (lambda x:x)
was ergibt,True
obf
es sich um eine Funktion handelt undFalse
ob dies nicht der Fall ist. Aber ich denke, ich bevorzugeisinstance (f, types.FunctionType)
, was sich weniger ad hoc anfühlt. Ich wollte es tuntype (f) is function
, aber das funktioniert nicht.quelle
Nach früheren Antworten habe ich Folgendes gefunden:
quelle
Sie könnten dies versuchen:
oder noch etwas bizarreres:
quelle
Wenn der Code den Aufruf weiterführt, wenn der Wert aufrufbar ist, führen Sie einfach den Aufruf aus und fangen Sie ab
TypeError
.quelle
x
hat.Das Folgende ist ein "Repr-Weg", um es zu überprüfen. Es funktioniert auch mit Lambda.
quelle
Das funktioniert bei mir:
quelle
"<type 'function'>"
, für eine ganze Zahl bekomme ich"<type 'int'>"
, also sehe ich nicht, wie es für Sie funktioniert: /open
als Funktion betrachtet werden?str(type(open))
gibt<class 'builtin_function_or_method'>
in Python 3.