J'ai une variable, x
et je veux savoir si elle pointe vers une fonction ou non.
J'avais espéré pouvoir faire quelque chose comme:
>>> isinstance(x, function)
Mais cela me donne:
Traceback (most recent call last):
File "<stdin>", line 1, in ?
NameError: name 'function' is not defined
La raison pour laquelle j'ai choisi c'est parce que
>>> type(x)
<type 'function'>
insepct.getsource
sur une variété d'objets, et il importe en fait non pas si l'objet était appelable mais si c'était quelque chose qui donnerait `` une fonction ''type(obj)
. Depuis que Google m'a conduit ici, je dirais que le commentaire d'AsTeR était la réponse la plus utile (pour moi). Il existe de nombreux autres endroits sur Internet à découvrir__call__
ou à découvrircallable
.Réponses:
Si c'est pour Python 2.x ou pour Python 3.2+, vous pouvez également utiliser
callable()
. Auparavant, il était obsolète, mais il n'est plus obsolète, vous pouvez donc le réutiliser. Vous pouvez lire la discussion ici: http://bugs.python.org/issue10518 . Vous pouvez le faire avec:Si c'est pour Python 3.x mais avant 3.2, vérifiez si l'objet a un
__call__
attribut. Vous pouvez le faire avec:L'
types.FunctionTypes
approche souvent suggérée n'est pas correcte car elle ne couvre pas de nombreux cas que vous souhaiteriez probablement qu'elle passe, comme avec les fonctions intégrées:La bonne façon de vérifier les propriétés des objets de type canard est de leur demander s'ils charlatanent, et non de voir s'ils tiennent dans un conteneur de la taille d'un canard. Ne l'utilisez
types.FunctionType
que si vous avez une idée très précise de ce qu'est une fonction.la source
Les types intégrés qui n'ont pas de constructeurs dans l'espace de noms intégré (par exemple, fonctions, générateurs, méthodes) sont dans le
types
module. Vous pouvez utilisertypes.FunctionType
dans unisinstance
appel:Notez que cela utilise une notion très spécifique de "fonction" qui n'est généralement pas ce dont vous avez besoin. Par exemple, il rejette
zip
(techniquement une classe):open
(les fonctions intégrées ont un type différent):et
random.shuffle
(techniquement une méthode d'unerandom.Random
instance cachée ):Si vous faites quelque chose de spécifique aux
types.FunctionType
instances, comme décompiler leur bytecode ou inspecter les variables de fermeture, utiliseztypes.FunctionType
, mais si vous avez juste besoin qu'un objet puisse être appelé comme une fonction, utilisezcallable
.la source
isinstance(f, (types.FunctionType, types.BuiltinFunctionType, functools.partial))
ou vérifierf.func
dans un tel cas.@foo
que je peux utiliser à la fois comme@foo
et comme@foo(some_parameter)
. Il doit ensuite vérifier avec quoi il est appelé, par exemple la fonction à décorer (premier cas) ou le paramètre (le deuxième cas, dans lequel il doit renvoyer un autre décorateur).types.BuiltinFunctionType
est également le type de méthodes intégrées ("normales") , que vous ne voulez probablement pas autoriser, si vous ne suivez pas lacallable
route.Depuis Python 2.1, vous pouvez importer à
isfunction
partir duinspect
module.la source
open
ethasattr
.inspect.isfunction
docstring: "Retourne vrai si l'objet est une fonction définie par l'utilisateur."La réponse acceptée était au moment où elle a été jugée correcte. Il s'avère qu'il n'y a pas de substitut pour
callable()
, qui est de retour dans Python 3.2: Spécifiquement,callable()
vérifie letp_call
champ de l'objet testé. Il n'y a pas d'équivalent Python simple. La plupart des tests proposés sont corrects la plupart du temps:Nous pouvons y jeter une clé à molette en retirant le
__call__
de la classe. Et juste pour garder les choses encore plus excitantes, ajoutez un faux__call__
à l'instance!Notez que ce n'est vraiment pas appelable:
callable()
renvoie le résultat correct:Mais
hasattr
c'est faux :can_o_spam
a cet attribut après tout; il n'est tout simplement pas utilisé lors de l'appel de l'instance.Encore plus subtil,
isinstance()
se trompe également:Étant donné que nous avons utilisé cette vérification plus tôt et supprimé la méthode,
abc.ABCMeta
le résultat est mis en cache. On peut dire que c'est un bug dansabc.ABCMeta
. Cela dit, il n'y a vraiment pas de façon possible , il pourrait produire un résultat plus précis que le résultat qu'en utilisantcallable()
lui - même, puisque latypeobject->tp_call
méthode de fente n'est pas accessible de toute autre manière.Utilisez simplement
callable()
la source
hasattr(o, '__call__')
approche et pourquoicallable()
, si disponibles, supérieurs.Les éléments suivants doivent renvoyer un booléen:
la source
L'outil 2to3 de Python ( http://docs.python.org/dev/library/2to3.html ) suggère:
Il semble que cela ait été choisi à la place de la
hasattr(x, '__call__')
méthode en raison de http://bugs.python.org/issue7006 .la source
callable()
de py3.3: bugs.python.org/issue10518#msg122309callable(x)
sera de retour vrai si l'objet passé peut être appelé en Python, mais la fonction n'existe pas en Python 3.0, et à proprement parler ne distinguera pas:Vous obtiendrez
<class 'A'> True
et<type function> True
en sortie.isinstance
fonctionne parfaitement pour déterminer si quelque chose est une fonction (essayezisinstance(b, types.FunctionType)
); si vous êtes vraiment intéressé à savoir si quelque chose peut être appelé, vous pouvez soit l'utiliser,hasattr(b, '__call__')
soit l'essayer.Bien sûr, cela ne vous dira pas si c'est appelable mais lance un
TypeError
quand il s'exécute, ou n'est pas appelable en premier lieu. Cela ne vous concerne peut-être pas.la source
Si vous voulez détecter tout ce qui ressemble syntaxiquement à une fonction: une fonction, une méthode, un fun / meth intégré, lambda ... mais exclure les objets appelables (objets avec la
__call__
méthode définie), alors essayez celui-ci:J'ai comparé cela avec le code de
is*()
vérification duinspect
module et l'expression ci-dessus est beaucoup plus complète, surtout si votre objectif est de filtrer les fonctions ou de détecter les propriétés régulières d'un objet.la source
types
module. Je testais unemake_stemmer()
usine qui renvoyait parfois une fonction et parfois uneStemmer
instance appelable , et j'avais besoin de détecter la différence.Essayez d'utiliser
callable(x)
.la source
Si vous avez appris
C++
, vous devez être familier avec,function object
oufunctor
signifie tout objet qui peutbe called as if it is a function
.En C ++,
an ordinary function
est un objet fonction, tout comme un pointeur de fonction; plus généralement, il en est de même d'un objet d'une classe qui définitoperator()
. En C ++ 11 et supérieur,the lambda expression
c'estfunctor
aussi le cas.Similitude, en Python, ce
functors
sont touscallable
.An ordinary function
peut être appelable,a lambda expression
peut être appelable, afunctional.partial
peut être appelable, les instances declass with a __call__() method
peuvent être appelables.Ok, revenons à la question:
I have a variable, x, and I want to know whether it is pointing to a function or not.
Ensuite, je fais une expérience en utilisant ces codes:
Je dessine un tableau des types de foncteurs appelables en utilisant les données.
tel que:
la source
Comme réponse acceptée, John Feminella a déclaré que:
Même s'il existe deux bibliothèques pour distinguer strictement les fonctions, je dessine un tableau comparable exhaustif:
8.9. types - Création de type dynamique et noms pour les types intégrés - Documentation Python 3.7.0
30.13. inspect - Inspecter des objets vivants - Documentation Python 3.7.0
Le "typage canard" est une solution privilégiée à usage général:
Quant à la fonction intégrée
Quand aller encore une étape pour vérifier si la fonction intégrée ou la fonction définie par l'utilisateur
Déterminez si
builtin function
Sommaire
Utilisez
callable
pour esquiver le type en vérifiant une fonction,utilisez
types.BuiltinFunctionType
si vous avez spécifié la demande.la source
Une fonction est juste une classe avec une
__call__
méthode, vous pouvez donc fairePar exemple:
C'est la "meilleure" façon de le faire, mais selon la raison pour laquelle vous devez savoir si c'est appelable ou note, vous pouvez simplement le mettre dans un bloc try / execpt:
C'est discutable si try / except est plus Python'y que do
if hasattr(x, '__call__'): x()
.. Je dirais quehasattr
c'est plus précis, car vous n'attraperez pas accidentellement la mauvaise TypeError, par exemple:la source
Voici quelques autres façons:
Voici comment j'ai trouvé le second:
la source
Au lieu de vérifier pour
'__call__'
( ce qui est exclusif à des fonctions), vous pouvez vérifier si une fonction définie par l' utilisateur a des attributsfunc_name
,func_doc
etc. Cela ne fonctionne pas pour les méthodes.Une autre façon de vérifier est d'utiliser la
isfunction()
méthode duinspect
module.Pour vérifier si un objet est une méthode, utilisez
inspect.ismethod()
la source
Étant donné que les classes ont également une
__call__
méthode, je recommande une autre solution:la source
hasattr(obj, '__call__')
est ambiguë.Notez que les classes Python sont également appelables.
Pour obtenir des fonctions (et par fonctions, nous entendons des fonctions standard et des lambdas), utilisez:
la source
Quelle que soit la fonction est une classe, vous pouvez prendre le nom de la classe d'instance x et comparer:
la source
Les solutions utilisant
hasattr(obj, '__call__')
etcallable(.)
mentionnées dans certaines des réponses ont un inconvénient principal: les deux retournent égalementTrue
pour les classes et les instances de classes avec une__call__()
méthode. Par exemple.Une bonne façon de vérifier si un objet est une fonction définie par l'utilisateur (et rien d'autre que ça) est d'utiliser
isfunction(.)
:Si vous devez rechercher d'autres types, jetez un œil à inspecter - Inspecter des objets vivants .
la source
Un vérificateur de fonction exact
callable est une très bonne solution. Cependant, je voulais traiter cela de la manière opposée à John Feminella. Au lieu de le traiter comme ceci:
Nous allons le traiter comme ceci:
Comment pourrions-nous le mettre en œuvre
Le module 'types' possède de nombreuses classes pour détecter les fonctions, les plus utiles étant types.FunctionType , mais il y en a aussi beaucoup d'autres, comme un type de méthode, un type intégré et un type lambda. Nous considérerons également un objet 'functools.partial' comme une fonction.
La manière simple de vérifier s'il s'agit d'une fonction consiste à utiliser une condition isinstance sur tous ces types. Auparavant, je voulais créer une classe de base qui hérite de tout ce qui précède, mais je suis incapable de le faire, car Python ne nous permet pas d'hériter de certaines des classes ci-dessus.
Voici un tableau de quelles classes peuvent classer quelles fonctions:
Dessus de table de fonction par kinght- 金
Le code qui le fait
Maintenant, c'est le code qui fait tout le travail que nous avons décrit ci-dessus.
Le faux était is_function (partial), parce que c'est une classe, pas une fonction, et c'est exactement des fonctions, pas des classes. Voici un aperçu à partir duquel vous pouvez essayer le code.
Conclusion
callable (obj) est la méthode préférée pour vérifier si un objet est une fonction si vous voulez passer en tapant du canard sur des absolus .
Notre fonction is_function (obj) personnalisée , peut-être avec quelques modifications est la méthode préférée pour vérifier si un objet est une fonction si vous ne comptez aucune instance de classe appelable comme une fonction, mais uniquement les fonctions définies intégrées , ou avec lambda , def , ou partielle .
Et je pense que tout se termine. Bonne journée!
la source
En Python3, j'ai trouvé ce
type (f) == type (lambda x:x)
qui donneTrue
sif
est une fonction etFalse
si elle ne l'est pas. Mais je pense que je préfèreisinstance (f, types.FunctionType)
, ce qui semble moins ponctuel. Je voulais le fairetype (f) is function
, mais cela ne fonctionne pas.la source
Suite aux réponses précédentes, j'ai trouvé ceci:
la source
Vous pouvez essayer ceci:
ou même quelque chose de plus bizarre:
la source
Si le code continue d'exécuter l'appel si la valeur est appelable, effectuez simplement l'appel et interceptez
TypeError
.la source
x
.Ce qui suit est un "moyen de repr" pour le vérifier. Cela fonctionne également avec lambda.
la source
Cela fonctionne pour moi:
la source
"<type 'function'>"
, pour un entier, je reçois"<type 'int'>"
, donc je ne vois pas comment cela fonctionne pour vous: /open
être considérée comme une fonction?str(type(open))
donne<class 'builtin_function_or_method'>
en Python 3.