¿Qué es una “llamada”?

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 una vez un error con paréntesis, lo que dio como resultado una excepción de “el objeto no se puede llamar”. Lo que es más, usar __init__ y __new__ lleva a preguntarse para qué se puede usar este maldito __call__ .

¿Podría darme algunas explicaciones, incluyendo ejemplos con el método mágico?

Related of "¿Qué es una “llamada”?"

Un llamable es cualquier cosa que se puede llamar.

El callable integrado (PyCallable_Check en objects.c) verifica si el argumento es:

  • una instancia de una clase con un método __call__ o
  • es de un tipo que tiene un miembro no nulo tp_call (c struct) que indica la capacidad de cancelación de otra manera (como en funciones, métodos, etc.)

El método llamado __call__ es ( según la documentación )

Se llama cuando la instancia es “llamada” como una función

Ejemplo

 class Foo: def __call__(self): print 'called' foo_instance = Foo() foo_instance() #this is calling the __call__ method 

De las fonts object.c de Python:

 /* Test whether an object can be called */ int PyCallable_Check(PyObject *x) { if (x == NULL) return 0; if (PyInstance_Check(x)) { PyObject *call = PyObject_GetAttrString(x, "__call__"); if (call == NULL) { PyErr_Clear(); return 0; } /* Could test recursively but don't, for fear of endless recursion if some joker sets self.__call__ = self */ Py_DECREF(call); return 1; } else { return x->ob_type->tp_call != NULL; } } 

Dice:

  1. Si un objeto es una instancia de alguna clase, entonces es llamable si tiene el atributo __call__ .
  2. De lo contrario, el objeto x es llamable iff x->ob_type->tp_call != NULL

Descipción del campo tp_call :

ternaryfunc tp_call Un puntero opcional a una función que implementa la llamada al objeto. Esto debería ser NULL si el objeto no es llamable. La firma es la misma que para PyObject_Call (). Este campo es heredado por subtipos.

Siempre se puede usar la función callable incorporada para determinar si el objeto dado es invocable o no; o mejor aún, simplemente llámalo y captura TypeError más tarde. callable se elimina en Python 3.0 y 3.1, use callable = lambda o: hasattr(o, '__call__') o isinstance(o, collections.Callable) .

Ejemplo, una implementación de caché simplista:

 class Cached: def __init__(self, function): self.function = function self.cache = {} def __call__(self, *args): try: return self.cache[args] except KeyError: ret = self.cache[args] = self.function(*args) return ret 

Uso:

 @Cached def ack(x, y): return ack(x-1, ack(x, y-1)) if x*y else (x + y + 1) 

Ejemplo de la biblioteca estándar, archivo site.py , definición de las site.py integradas exit() y quit() :

 class Quitter(object): def __init__(self, name): self.name = name def __repr__(self): return 'Use %s() or %s to exit' % (self.name, eof) def __call__(self, code=None): # Shells like IDLE catch the SystemExit, but listen when their # stdin wrapper is closed. try: sys.stdin.close() except: pass raise SystemExit(code) __builtin__.quit = Quitter('quit') __builtin__.exit = Quitter('exit') 

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 definas una función, python crea un objeto invocable. En el ejemplo, podría definir la función func de estas maneras (es lo mismo):

 class a(object): def __call__(self, *args): print 'Hello' func = a() # or ... def func(*args): print 'Hello' 

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 ()

Déjame explicarte al revés:

Considera esto…

 foo() 

… como azúcar sintáctica para:

 foo.__call__() 

Donde foo puede ser cualquier objeto que responda a __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:

 int('10') unicode(10) 

Esencialmente estás haciendo:

 int.__call__('10') unicode.__call__(10) 

También es por eso que no tienes foo = new int en Python: simplemente haces que el objeto de clase devuelva una instancia de él en __call__ . La forma en que Python resuelve esto es muy elegante en mi opinión.

Un Callable es un objeto que tiene el método __call__ . Esto significa que puedes falsificar funciones que se pueden llamar o hacer cosas interesantes como la aplicación de función parcial donde tomas una función y agregas algo que la mejora o completa en algunos de los parámetros, devolviendo algo que puede llamarse a su vez (conocido como Currying en los círculos de progtwigción funcional ).

Ciertos errores tipográficos harán que el intérprete intente llamar algo que no pretendía, como (por ejemplo) una cadena. Esto puede producir errores cuando el intérprete intenta ejecutar una aplicación que no se puede llamar. Puedes ver que esto sucede en un intérprete de python haciendo algo como la transcripción a continuación.

 [nigel@k9 ~]$ python Python 2.5 (r25:51908, Nov 6 2007, 15:55:44) [GCC 4.1.2 20070925 (Red Hat 4.1.2-27)] on linux2 Type "help", "copyright", "credits" or "license" for more information. >>> 'aaa'() # <== Here we attempt to call a string. Traceback (most recent call last): File "", line 1, in  TypeError: 'str' object is not callable >>> 

En pocas palabras, un “llamable” es algo que se puede llamar como un método. La función incorporada “callable ()” le dirá si algo parece ser llamable, al igual que la verificación de una propiedad de llamada . Las funciones son invocables al igual que las clases, las instancias de las clases pueden ser invocables. Ver más sobre esto aquí y aquí .

__call__ hace que cualquier objeto sea llamable como una función.

Este ejemplo dará salida a 8:

 class Adder(object): def __init__(self, val): self.val = val def __call__(self, val): return self.val + val func = Adder(5) print func(3) 

En Python, un objeto llamable es un objeto cuyo tipo tiene un método __call__ :

 >>> class Foo: ... pass ... >>> class Bar(object): ... pass ... >>> type(Foo).__call__(Foo) <__main__.Foo instance at 0x711440> >>> type(Bar).__call__(Bar) <__main__.Bar object at 0x712110> >>> def foo(bar): ... return bar ... >>> type(foo).__call__(foo, 42) 42 

Tan sencillo como eso 🙂

Esto por supuesto puede ser sobrecargado:

 >>> class Foo(object): ... def __call__(self): ... return 42 ... >>> f = Foo() >>> f() 42 

Es algo que puedes poner “(args)” después y esperar que funcione. Un reclamable es usualmente un método o una clase. Los métodos son llamados, las clases son instanciadas.

Para verificar la función o el método de clase es llamable o no, eso significa que podemos llamar a esa función.

 Class A: def __init__(self,val): self.val = val def bar(self): print "bar" obj = A() callable(obj.bar) True callable(obj.__init___) False def foo(): return "s" callable(foo) True callable(foo()) False 

Llamable es un tipo o clase de “Función incorporada o Método” con una llamada de método

 >>> type(callable)  >>> 

Ejemplo: imprimir es un objeto llamable. 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.

 >>> type(print)  >>> print.__call__(10) 10 >>> print(10) 10 >>> 

Gracias. Saludos, Maris

__call__ implementa el método especial __call__ para que cualquier objeto con dicho método sea llamable.