Ahora que está claro qué es una metaclase , hay un concepto asociado que uso todo el tiempo sin saber lo que realmente significa.
Supongo que todos cometieron un error con paréntesis, lo que resultó en una excepción de "objeto no invocable". Además, usar __init__
y __new__
conducir a preguntarse para qué __call__
se puede usar este sangriento .
¿Podría darme algunas explicaciones, incluidos ejemplos con el método mágico?
Respuestas:
Un invocable es cualquier cosa que se pueda llamar.
El built-in exigible (PyCallable_Check en objects.c) comprueba si el argumento es ya sea:
__call__
método oEl método nombrado
__call__
es (de acuerdo con la documentación )Ejemplo
fuente
callable
en realidad le dice si algo es invocable o no, mientras que la verificación__call__
no le dice nada; Si un objetoo
proporciona__getattribute__
o__getattr__
,hasattr(o, '__call__')
puede devolver True,o
aún no será invocable porque Python omite__getattribute__
y__getattr__
para las llamadas. Por lo tanto, la única forma real de verificar si algo se puede llamar es EAFP.callable()
en Python 3.x : " Esta función se eliminó primero en Python 3.0 y luego se recuperó en Python 3.2 ".tp_call
se verifica la presencia de . Vea la implementación de PyCallable_Check , son 3 líneas.De las fuentes de Python object.c :
Dice:
__call__
atributo.x
es invocable six->ob_type->tp_call != NULL
Descipción de
tp_call
campo :Siempre puede usar la
callable
función incorporada para determinar si el objeto dado es invocable o no; o mejor aún, simplemente llámalo y capturaTypeError
más tardecallable
se elimina en Python 3.0 y 3.1, usecallable = lambda o: hasattr(o, '__call__')
oisinstance(o, collections.Callable)
.Ejemplo, una implementación de caché simplista:
Uso:
Ejemplo de biblioteca estándar, archivo
site.py
, definición de funciones integradasexit()
yquit()
:fuente
def f(): ...
, y la clase de objetos comoclass C: ...
es decir,f
,''.strip
,len
, yC
todos son invocable. Las instancias que tienen un__call__()
método en su clase son relativamente raras.Un objeto invocable es un objeto que le permite usar paréntesis redondos () y eventualmente pasar algunos parámetros, al igual que las funciones.
Cada vez que define una función, Python crea un objeto invocable. Por ejemplo, podría definir la función func de estas formas (es lo mismo):
Podría usar este método en lugar de métodos como doit o run , creo que es más claro ver obj () que obj.doit ()
fuente
Déjame explicarte al revés:
Considera esto...
... como azúcar sintáctica para:
¿Dónde
foo
puede haber cualquier objeto que responda__call__
? Cuando digo cualquier objeto, lo digo en serio: tipos incorporados, sus propias clases y sus instancias.En el caso de los tipos incorporados, cuando escribe:
Básicamente estás haciendo:
Esa es también la razón por la que no tienes
foo = new int
en Python: solo haces que el objeto de clase devuelva una instancia de él__call__
. La forma en que Python resuelve esto es muy elegante en mi opinión.fuente
type(int).__call__(int, '10')
ytype(unicode).__call__(unicode, '10')
. Los Dunders siempre son llamados en su clase, no a través de la instancia. Y nunca pasan por la metaclase tampoco. Para la mayoría de los casos, eso es solo una trampa, pero a veces es importante.Un invocable es un objeto que tiene el
__call__
método. Esto significa que puede falsificar funciones invocables o hacer cosas interesantes como la aplicación de función parcial donde toma una función y agrega algo que la mejora o completa algunos de los parámetros, devolviendo algo que se puede llamar a su vez (conocido como Curry en círculos de programación funcional )Ciertos errores tipográficos harán que el intérprete intente llamar a algo que no tenía intención, como (por ejemplo) una cadena. Esto puede producir errores en los que el intérprete intenta ejecutar una aplicación no invocable. Puede ver que esto sucede en un intérprete de Python haciendo algo como la transcripción a continuación.
fuente
__call__
hace que cualquier objeto sea invocable como una función.Este ejemplo generará 8:
fuente
En pocas palabras, un "invocable" es algo que se puede llamar como un método. La función integrada "invocable ()" le dirá si algo parece invocable, al igual que la comprobación de una propiedad de llamada . Las funciones son invocables como son las clases, las instancias de clase pueden ser invocables. Vea más sobre esto aquí y aquí .
fuente
En Python un invocable es un objeto cuyo tipo tiene un
__call__
método:Tan sencillo como eso :)
Esto, por supuesto, se puede sobrecargar:
fuente
Verificar que la función o método de la clase sea invocable o no, eso significa que podemos llamar a esa función.
fuente
callable(obj.__init___)
que no tiene un guión bajo adicional (como en AttributeError)? Si no es así, ¿estás seguro de que la respuesta no esTrue
para esa?Es algo que puede poner "(args)" después y esperar que funcione. Un invocable suele ser un método o una clase. Se llaman métodos, se instancian las clases.
fuente
los invocables implementan el
__call__
método especial para que cualquier objeto con dicho método pueda invocarse.fuente
__call__
no se podrá llamar si la clase no define dicho método.Llamable es un tipo o clase de "función o método integrado" con una llamada a método
Ejemplo: print es un objeto invocable. Con una función incorporada __call__ Cuando invoca la función de impresión , Python crea un objeto de tipo print e invoca su método __call__ pasando los parámetros si los hay.
Gracias. Saludos, Maris
fuente
print
función, Python crea un objeto de tipo print e invoca su método__call__
". Python no crea un objeto de impresión. Simplemente llama a algo equivalente atype(print).__call__(print, *args, **kwargs)
. Y la primera oración no tiene mucho sentido. Parece que está confundiendo un objeto invocable y "invoca" la función.