Tengo una variable, x
y quiero saber si está apuntando a una función o no.
Esperaba poder hacer algo como:
>>> isinstance(x, function)
Pero eso me da:
Traceback (most recent call last):
File "<stdin>", line 1, in ?
NameError: name 'function' is not defined
La razón por la que elegí eso es porque
>>> type(x)
<type 'function'>
insepct.getsource
en una variedad de objetos, y en realidad no importa si el objeto era invocable, sino si era algo para lo que daría 'función'type(obj)
. Como google me llevó aquí, diría que el comentario de AsTeR fue la respuesta más útil (para mí). Hay muchos otros lugares en Internet para que la gente los descubra__call__
o descubracallable
.Respuestas:
Si esto es para Python 2.xo Python 3.2+, también puede usarlo
callable()
. Solía estar en desuso, pero ahora está en desuso, por lo que puede volver a usarlo. Puede leer la discusión aquí: http://bugs.python.org/issue10518 . Puedes hacer esto con:Si esto es para Python 3.x pero antes de 3.2, verifique si el objeto tiene un
__call__
atributo. Puedes hacer esto con:El
types.FunctionTypes
enfoque sugerido con frecuencia no es correcto porque no cubre muchos casos que presumiblemente desearía que pasara, como ocurre con las incorporadas:La forma correcta de verificar las propiedades de los objetos con tipo de pato es preguntarles si graznan, no para ver si caben en un contenedor del tamaño de un pato. No lo use a
types.FunctionType
menos que tenga una idea muy específica de lo que es una función.fuente
Los tipos incorporados que no tienen constructores en el espacio de nombres incorporado (por ejemplo, funciones, generadores, métodos) están en el
types
módulo. Puedes usartypes.FunctionType
en unaisinstance
llamada:Tenga en cuenta que esto utiliza una noción muy específica de "función" que generalmente no es lo que necesita. Por ejemplo, rechaza
zip
(técnicamente una clase):open
(las funciones integradas tienen un tipo diferente):y
random.shuffle
(técnicamente un método de unarandom.Random
instancia oculta ):Si está haciendo algo específico para las
types.FunctionType
instancias, como descompilar su bytecode o inspeccionar las variables de cierre, usetypes.FunctionType
, pero si solo necesita que un objeto sea invocable como una función, usecallable
.fuente
isinstance(f, (types.FunctionType, types.BuiltinFunctionType, functools.partial))
o verificarf.func
en tal caso.@foo
que pueda usar como@foo
y como@foo(some_parameter)
. Luego necesita verificar con qué se llama, por ejemplo, la función para decorar (primer caso) o el parámetro (el segundo caso, en el que necesita devolver un decorador adicional).types.BuiltinFunctionType
también es el tipo de métodos integrados ("normales") , que probablemente no desee permitir, si no va por lacallable
ruta.Desde Python 2.1 puede importar
isfunction
desde elinspect
módulo.fuente
open
yhasattr
.inspect.isfunction
cadena de documentación: "Devuelve verdadero si el objeto es una función definida por el usuario".La respuesta aceptada en el momento en que se ofreció se pensó que era correcta. Como resultado, no hay sustituto para
callable()
, que está de vuelta en Python 3.2: Específicamente,callable()
verifica eltp_call
campo del objeto que se está probando. No hay un equivalente de Python simple. La mayoría de las pruebas sugeridas son correctas la mayor parte del tiempo:Podemos arrojar una llave inglesa en esto eliminando el
__call__
de la clase. Y solo para mantener las cosas más emocionantes, ¡agregue un falso__call__
a la instancia!Tenga en cuenta que esto realmente no es invocable:
callable()
devuelve el resultado correcto:Pero
hasattr
está mal :can_o_spam
tiene ese atributo después de todo; simplemente no se usa cuando se llama a la instancia.Aún más sutil,
isinstance()
también se equivoca:Debido a que usamos esta verificación antes y luego eliminamos el método,
abc.ABCMeta
almacena el resultado en caché. Podría decirse que esto es un errorabc.ABCMeta
. Dicho esto, realmente no hay forma posible de que pueda producir un resultado más preciso que el resultado que si se usacallable()
solo, ya que eltypeobject->tp_call
método de ranura no es accesible de ninguna otra manera.Solo usa
callable()
fuente
hasattr(o, '__call__')
enfoque y por quécallable()
, si está disponible, es superior.Lo siguiente debería devolver un booleano:
fuente
La herramienta 2to3 de Python ( http://docs.python.org/dev/library/2to3.html ) sugiere:
Parece que esto se eligió en lugar del
hasattr(x, '__call__')
método debido a http://bugs.python.org/issue7006 .fuente
callable()
de py3.3: bugs.python.org/issue10518#msg122309callable(x)
se devolverá true si el objeto pasado puede ser llamado en Python, pero la función no existe en Python 3.0, y hablando con propiedad, no va a distinguir entre:Obtendrá
<class 'A'> True
y<type function> True
como salida.isinstance
funciona perfectamente bien para determinar si algo es una función (pruebaisinstance(b, types.FunctionType)
); Si está realmente interesado en saber si se puede llamar a algo, puede usarlohasattr(b, '__call__')
o simplemente probarlo.Esto, por supuesto, no le dirá si es invocable pero arroja un
TypeError
cuando se ejecuta, o no es invocable en primer lugar. Eso puede no importarte.fuente
Si desea detectar todo lo que se parece sintácticamente a una función: una función, método, diversión / metanfetamina incorporada, lambda ... pero excluye los objetos invocables (objetos con
__call__
método definido), intente este:Comparé esto con el código de
is*()
verificaciones en elinspect
módulo y la expresión anterior es mucho más completa, especialmente si su objetivo es filtrar cualquier función o detectar propiedades regulares de un objeto.fuente
types
módulo. Estaba probando unamake_stemmer()
fábrica que a veces devolvía una función y otras unaStemmer
instancia invocable , y necesitaba detectar la diferencia.Intenta usarlo
callable(x)
.fuente
Si ha aprendido
C++
, debe estar familiarizado confunction object
ofunctor
, significa cualquier objeto que puedabe called as if it is a function
.En C ++,
an ordinary function
es un objeto de función, y también lo es un puntero de función; más generalmente, también es un objeto de una clase que defineoperator()
. En C ++ 11 y superior,the lambda expression
es elfunctor
también.Similitud, en Python, esos
functors
son todoscallable
.An ordinary function
puede ser invocable,a lambda expression
puede invocarse,functional.partial
puede invocarse, las instancias declass with a __call__() method
pueden invocarse.Ok, vuelve a la pregunta:
I have a variable, x, and I want to know whether it is pointing to a function or not.
Luego hago un experimento usando esos códigos:
Dibujo una tabla de tipos de functor invocables utilizando los datos.
como:
fuente
Como la respuesta aceptada, John Feminella declaró que:
Aunque hay dos bibliotecas para distinguir las funciones estrictamente, dibujo una tabla exhaustiva comparable:
8.9. tipos - Creación dinámica de tipos y nombres para tipos incorporados - Documentación de Python 3.7.0
30.13. inspeccionar - Inspeccionar objetos vivos - Documentación de Python 3.7.0
La "tipificación de pato" es una solución preferida para fines generales:
En cuanto a la función incorporada
Cuando vaya un paso más para verificar si la función integrada o la función definida por el usuario
Determinar si
builtin function
Resumen
Emplee
callable
para esquivar el tipo que verifica una función.Úselo
types.BuiltinFunctionType
si tiene una demanda más específica.fuente
Una función es solo una clase con un
__call__
método, por lo que puede hacerPor ejemplo:
Esa es la "mejor" forma de hacerlo, pero dependiendo de por qué necesita saber si es invocable o una nota, puede ponerlo en un bloque try / execpt:
Es discutible si try / except es más Python'y que hacerlo
if hasattr(x, '__call__'): x()
... Diría quehasattr
es más preciso, ya que accidentalmente no detectará el TypeError incorrecto, por ejemplo:fuente
Aquí hay un par de otras formas:
Así es como se me ocurrió la segunda:
fuente
En lugar de comprobar
'__call__'
(que no es exclusivo de funciones), se puede comprobar si una función definida por el usuario tiene atributosfunc_name
,func_doc
etc. Esto no funciona para métodos.Otra forma de verificar es usar el
isfunction()
método delinspect
módulo.Para verificar si un objeto es un método, use
inspect.ismethod()
fuente
Como las clases también tienen
__call__
método, recomiendo otra solución:fuente
hasattr(obj, '__call__')
es ambigua.Tenga en cuenta que las clases de Python también son invocables.
Para obtener funciones (y por funciones nos referimos a funciones estándar y lambdas) use:
fuente
Cualquier función es una clase para que pueda tomar el nombre de la clase de instancia x y comparar:
fuente
Las soluciones que se usan
hasattr(obj, '__call__')
y secallable(.)
mencionan en algunas de las respuestas tienen un inconveniente principal: ambas también regresanTrue
para clases e instancias de clases con un__call__()
método. P.ej.Una forma adecuada de verificar si un objeto es una función definida por el usuario (y nada más que eso) es usar
isfunction(.)
:Si necesita buscar otros tipos, eche un vistazo a inspeccionar: inspeccione objetos vivos .
fuente
Un verificador de función exacta
invocable es una muy buena solución. Sin embargo, quería tratar esto de la manera opuesta a John Feminella. En lugar de tratarlo como este dicho:
Lo trataremos así:
¿Cómo lo implementaríamos?
El módulo 'tipos' tiene muchas clases para detectar funciones, siendo las más útiles tipos.FunctionType , pero también hay muchas otras, como un tipo de método, un tipo incorporado y un tipo lambda. También consideraremos un objeto 'functools.partial' como una función.
La forma simple de verificar si es una función es mediante el uso de una condición isinstance en todos estos tipos. Anteriormente, quería hacer una clase base que herede de todo lo anterior, pero no puedo hacerlo, ya que Python no nos permite heredar de algunas de las clases anteriores.
Aquí hay una tabla de qué clases pueden clasificar qué funciones:
Tabla de funciones de arriba por kinght- 金
El código que lo hace
Ahora, este es el código que hace todo el trabajo que describimos desde arriba.
El falso era is_function (parcial), porque es una clase, no una función, y esto es exactamente funciones, no clases. Aquí hay una vista previa para que pruebe el código.
Conclusión
invocable (obj) es el método preferido para verificar si un objeto es una función si quiere ir escribiendo pato sobre absolutos .
Nuestra función is_function (obj) personalizada , tal vez con algunas ediciones es el método preferido para verificar si un objeto es una función si no cuenta ninguna instancia de clase invocable como una función, sino solo funciones definidas integradas , o con lambda , def o parcial .
Y creo que eso lo envuelve todo. ¡Tenga un buen día!
fuente
En Python3 se me ocurrió
type (f) == type (lambda x:x)
qué rendimientoTrue
sif
es una función yFalse
si no lo es. Pero creo que prefieroisinstance (f, types.FunctionType)
, que se siente menos ad hoc. Quería hacerlotype (f) is function
, pero eso no funciona.fuente
Después de las respuestas anteriores, se me ocurrió esto:
fuente
Podrías probar esto:
o incluso algo más extraño:
fuente
Si el código continuará realizando la llamada si el valor es invocable, solo realice la llamada y captura
TypeError
.fuente
x
tiene.La siguiente es una "forma de repr" para verificarlo. También funciona con lambda.
fuente
Esto funciona para mi:
fuente
"<type 'function'>"
, para un número entero, obtengo"<type 'int'>"
, así que no veo cómo te está funcionando: /open
considerarse la función incorporada?str(type(open))
da<class 'builtin_function_or_method'>
en Python 3.