2008-09-16 22 views
6

Tengo una función en Python que itera sobre los atributos devueltos desde dir (obj), y quiero verificar si alguno de los objetos que contiene es una función, método, función incorporada, etc. Normalmente, usted podría usar callable() para esto, pero no quiero incluir clases. Lo mejor que he encontrado hasta ahora es:¿Hay alguna forma común de verificar en Python si un objeto es cualquier tipo de función?

isinstance(obj, (types.BuiltinFunctionType, types.FunctionType, types.MethodType)) 

¿Hay alguna manera más segura de realizar este control en el futuro?

Edité: Me equivoqué al decir cuando dije: "Normalmente podría usar callable() para esto, pero no quiero descalificar clases". De hecho, do quiero descalificar clases. Quiero hacer coincidir las funciones solo, no las clases.

Respuesta

13

La inspeccionar módulo tiene exactamente lo que desea:

inspect.isroutine(obj) 

FYI, el código es:

def isroutine(object): 
    """Return true if the object is any kind of function or method.""" 
    return (isbuiltin(object) 
      or isfunction(object) 
      or ismethod(object) 
      or ismethoddescriptor(object)) 
+2

isroutine() devuelve False para los parciales. hasattr (obj, '__call__') devuelve True para parciales. – Jim

2
if hasattr(obj, '__call__'): pass 

se ajusta a esta también en mejor con la filosofía "duck typing" de Python, ya que realmente no se preocupan lo que sea, siempre que se le puede llamar.

Vale la pena señalar que callable() se está eliminando de Python y no está presente en 3.0.

+1

A tener en cuenta que esto sólo funcionará para las clases de nuevo estilo. Obtienes False para las clases de estilo antiguo. –

5

Si desea excluir clases y otros objetos aleatorios que pueden tener un método __call__, y sólo comprobar las funciones y los métodos, estas tres funciones en el inspect module

inspect.isfunction(obj) 
inspect.isbuiltin(obj) 
inspect.ismethod(obj) 

deben hacer lo que quiere en un futuro a prueba de fuego

+0

Upvoted, prefiera la solución hasattr porque puede definir un elemento __call__ en una clase definida por el usuario y hasattr le dirá con mucho gusto que la clase tiene el atributo __call__, incluso si no es una función. –

+0

No veo cómo esto es mejor que la solución en mi comentario original? Aún debe verificar los tres de forma explícita. –

1

Dependiendo de lo que entendemos por 'clase':

callable(obj) and not inspect.isclass(obj) 

o:

callable(obj) and not isinstance(obj, types.ClassType) 

Por ejemplo, los resultados son diferentes para 'dict':

>>> callable(dict) and not inspect.isclass(dict) 
False 
>>> callable(dict) and not isinstance(dict, types.ClassType) 
True 
Cuestiones relacionadas