2010-12-08 9 views
11

Miré this thread pero algunos de los conceptos están por encima de mi nivel actual. En Python 2.x, existe el método incorporado callable(); ¿Hay alguna manera simple de verificar si algo es invocable o no usar Python 3?alternativo a llamable(), para uso en Python 3

+0

No estoy de acuerdo con su elección de respuesta aceptada. Creo que [la respuesta de joeforker] (http://stackoverflow.com/a/10045780/5420829) es mejor. –

+0

Estoy de acuerdo. Mi respuesta ahora está desactualizada. Sería bueno si OP cambiara la respuesta a una de las actualmente válidas. –

Respuesta

9

En su lugar, puede hacer hasattr(object_name, '__call__'). A diferencia de Python 2.x, esto funciona para todos los objetos invocables, incluidas las clases.

+2

En Python 2.x, funciona para clases de estilo nuevo pero no de estilo antiguo. Recuerde, sin embargo, el '__call__' llamado en una clase (de nuevo estilo) es' type''s (o la metaclass de la clase), no de la clase. – kindall

+0

@kindall: Buen punto, vale la pena tener en cuenta. Aunque, por supuesto, sería bastante extraño si fuera diferente. Esto también le permite hacer cosas funky como 'class_name()()' –

+0

Tenga en cuenta que esto dará un falso positivo en el siguiente caso de esquina: 'clase C (objeto): pase; c = C(); c .__ call__ = lambda self: None'. Aunque 'c' ahora tiene una función como el atributo __call__,' c() 'fallará, aunque la comprobación' hasattr' tendrá éxito. No estoy seguro, pero tampoco puedo descartar un caso de esquina falso negativo, aunque de ser posible probablemente requeriría objetos implementados en C para activarlo. – mtraceur

17

callable() está de vuelta en Python 3.2.

Si tiene que usar Python 3.1 (muy poco probable) entonces, además de la comprobación de __call__ también existen las siguientes soluciones:

  • 2to3 cambia un callable(x) en isinstance(x, collections.Callable)

  • seis usos

    any("__call__" in klass.__dict__ for klass in type(x).__mro__) 
    

    Es decir, comprueba __call__ en las clases base. Esto me recuerda que debería preguntarle a Benjamin por qué. :)

Y, por último, por supuesto puede simplemente tratar:

try: 
    x = x() 
except TypeError: 
    pass 
+0

Gran referencia de 2to3 ... que es un argumento convincente para usar 'collections.Callable'. El ABC está en todas partes ahora, parece. – Russ

+6

Brillante. Pero prueba/excepto que el consejo es aterrador. – Shekhar

+0

@Shekhar: el manejo de excepciones no da miedo una vez que estás acostumbrado. –

38

Está de regreso. Python 3.2 tiene callable(); ya no es necesario utilizar una de las alternativas menos convenientes.