Sam
quiero saber la diferencia entre __init__
y __call__
métodos.
Por ejemplo:
class test:
def __init__(self):
self.a = 10
def __call__(self):
b = 20
gato más más
El primero se usa para inicializar un objeto recién creado y recibe los argumentos que se usan para hacerlo:
class Foo:
def __init__(self, a, b, c):
# ...
x = Foo(1, 2, 3) # __init__
El segundo implementa el operador de llamada de función.
class Foo:
def __call__(self, a, b, c):
# ...
x = Foo()
x(1, 2, 3) # __call__
-
Entonces el
__init__
El método se utiliza cuando el clase se llama para inicializar la instancia, mientras que el__call__
Se llama al método cuando el instancia se llama– pratikm
15 de enero de 2015 a las 17:58
-
Eso parece correcto, aparentemente las variables de instancia se pueden modificar durante la vida de una instancia, lo que puede ser beneficioso en algunos casos.
– Murphy
27 de diciembre de 2017 a las 19:38
-
en eso se llama al instanciar la clase: myfoo = Foo(1,4,7.8) llamar es una plantilla para llamar a la clase ya instanciada para hacer algo, digamos class Foo:\ def __call__(self, zzz) Luego, myfoo(12) llama a la clase para hacer lo que hace esa clase.
– usuario1270710
31/10/2018 a las 23:38
-
¿Cuál es el uso práctico de
__call__
?– mrgloom
13 de noviembre de 2019 a las 12:43
-
La respuesta de Dmitriy Sintsov a continuación plantea un punto muy importante, por lo que creo que debería llamar la atención aquí:
__call__
puede devolver un valor arbitrariomientras__init__
debe devolver Ninguno.– polvo de cantor
30 de marzo de 2020 a las 12:34
Avasal
Definición de una costumbre __call__()
El método permite llamar a la instancia de la clase como una función, no siempre modificando la instancia en sí.
In [1]: class A:
...: def __init__(self):
...: print "init"
...:
...: def __call__(self):
...: print "call"
...:
...:
In [2]: a = A()
init
In [3]: a()
call
-
__call__
no solo permite que una instancia se use como función… sino que define el cuerpo de la función que se ejecuta cuando una instancia se usa como función.– Arturo
1 de septiembre de 2019 a las 17:14
paolo maresca
En Python, las funciones son objetos de primera clase, esto significa que las referencias a funciones se pueden pasar en entradas a otras funciones y/o métodos, y ejecutarse desde dentro de ellas.
Instancias de Clases (también conocido como Objetos), se pueden tratar como si fueran funciones: páselos a otros métodos/funciones y llámelos. Para lograr esto, el __call__
la función de clase tiene que ser especializada.
def __call__(self, [args ...])
Toma como entrada un número variable de argumentos. Asumiendo x
ser una instancia de la Clase X
, x.__call__(1, 2)
es análogo a llamar x(1,2)
o la instancia misma como una función.
en Python, __init__()
se define correctamente como constructor de clase (así como __del__()
es el Destructor de clases). Por lo tanto, hay una distinción neta entre __init__()
y __call__()
: el primero construye una instancia de Class up, el segundo crea dicha instancia invocable como sería una función sin afectar el ciclo de vida del objeto en sí (es decir, __call__
no afecta el ciclo de vida de construcción/destrucción) pero puede modificar su estado interno (como se muestra a continuación).
Ejemplo.
class Stuff(object):
def __init__(self, x, y, range):
super(Stuff, self).__init__()
self.x = x
self.y = y
self.range = range
def __call__(self, x, y):
self.x = x
self.y = y
print '__call__ with (%d,%d)' % (self.x, self.y)
def __del__(self):
del self.x
del self.y
del self.range
>>> s = Stuff(1, 2, 3)
>>> s.x
1
>>> s(7, 8)
__call__ with (7,8)
>>> s.x
7
-
Entiendo el concepto, pero no la característica especial de modificando su estado interno. Si en el código anterior reemplazamos
def __call__
simplemente condef update
le damos a la clase unupdate
método que hace lo mismo. Ahora también puede modificar el estado interno, si se llama a continuación comos.update(7, 8)
. Asi es__call__
Entonces, ¿solo azúcar sintáctica?– Álex Povel
6 de abril de 2020 a las 19:16
-
Sí, bastante. Es solo un atajo para invocar un método en el objeto sin molestarse en especificarlo. Aparte de eso, es como cualquier otro método de instancia. Curiosamente, si lo decora con @classmethod, sirve tanto como un método de clase como para hacer que una instancia sea invocable. Pero dado que un método de clase no puede tomarse a sí mismo, no hay estado para pasar, y tratar de llamar a una clase como llama a un método
__init__
así que afortunadamente no rompe la construcción de la clase.– Chris Iván
13 de agosto de 2020 a las 3:57
Mudit Verma
__call__
hace que la instancia de una clase sea invocable. ¿Por qué sería necesario?
Técnicamente __init__
es llamado una vez por __new__
cuando se crea el objeto, para que pueda inicializarse.
Pero hay muchos escenarios en los que es posible que desee redefinir su objeto, digamos que ha terminado con su objeto y puede encontrar la necesidad de un nuevo objeto. Con __call__
puede redefinir el mismo objeto como si fuera nuevo.
Este es solo un caso, puede haber muchos más.
>>> class A:
... def __init__(self):
... print "From init ... "
...
>>> a = A()
From init ...
>>> a()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: A instance has no __call__ method
>>>
>>> class B:
... def __init__(self):
... print "From init ... "
... def __call__(self):
... print "From call ... "
...
>>> b = B()
From init ...
>>> b()
From call ...
>>>
-
Creo que esta debería ser la respuesta aceptada. Responde con precisión.
– Prasad Raghavendra
26 de marzo de 2020 a las 2:43
Vikram
__init__
sería tratado como Constructor donde como __call__
Los métodos se pueden llamar con objetos cualquier número de veces. Ambas cosas __init__
y __call__
Las funciones toman argumentos predeterminados.
-
Creo que esta debería ser la respuesta aceptada. Responde con precisión.
– Prasad Raghavendra
26 de marzo de 2020 a las 2:43
Intentaré explicar esto usando un ejemplo, suponga que desea imprimir un número fijo de términos de la serie de Fibonacci. Recuerda que los 2 primeros términos de la serie de Fibonacci son 1s. Ej: 1, 1, 2, 3, 5, 8, 13….
Desea que la lista que contiene los números de Fibonacci se inicialice solo una vez y luego se actualice. Ahora podemos usar el __call__
funcionalidad. Lee la respuesta de @mudit verma. Es como si quisiera que el objeto se pueda llamar como una función pero no se reinicialice cada vez que lo llame.
P.ej:
class Recorder:
def __init__(self):
self._weights = []
for i in range(0, 2):
self._weights.append(1)
print self._weights[-1]
print self._weights[-2]
print "no. above is from __init__"
def __call__(self, t):
self._weights = [self._weights[-1], self._weights[-1] + self._weights[-2]]
print self._weights[-1]
print "no. above is from __call__"
weight_recorder = Recorder()
for i in range(0, 10):
weight_recorder(i)
La salida es:
1
1
no. above is from __init__
2
no. above is from __call__
3
no. above is from __call__
5
no. above is from __call__
8
no. above is from __call__
13
no. above is from __call__
21
no. above is from __call__
34
no. above is from __call__
55
no. above is from __call__
89
no. above is from __call__
144
no. above is from __call__
Si observa la salida __init__
fue llamado solo una vez que fue cuando la clase fue instanciada por primera vez, más tarde el objeto fue llamado sin reinicializar.
Esto es funcionalmente dos preguntas en una: “¿Cuál es el
__init__
método para / ¿qué hace?” y “¿Cuál es el__call__
método para / ¿qué hace?” No veo ninguna razón a priori suponer que tienen algo que ver entre sí, y de hecho no es así, por lo que no hay una forma significativa de describir una “diferencia entre” ellos.– Karl Knechtel
27 de julio a las 21:43