Réponses:
Le premier est utilisé pour initialiser l'objet nouvellement créé et reçoit les arguments utilisés pour ce faire:
class Foo:
def __init__(self, a, b, c):
# ...
x = Foo(1, 2, 3) # __init__
Le second implémente l'opérateur d'appel de fonction.
class Foo:
def __call__(self, a, b, c):
# ...
x = Foo()
x(1, 2, 3) # __call__
__call__
?
La définition d'une __call__()
méthode personnalisée dans la méta-classe permet d'appeler l'instance de la classe en tant que fonction, sans modifier toujours l'instance elle-même.
In [1]: class A:
...: def __init__(self):
...: print "init"
...:
...: def __call__(self):
...: print "call"
...:
...:
In [2]: a = A()
init
In [3]: a()
call
__call__
permet non seulement d'utiliser une instance en tant que fonction ... mais définit le corps de la fonction qui est exécutée lorsqu'une instance est utilisée en tant que fonction.
En Python, les fonctions sont des objets de première classe, cela signifie: les références de fonction peuvent être passées en entrées à d'autres fonctions et / ou méthodes, et exécutées depuis l'intérieur.
Les instances de classes (ou objets) peuvent être traitées comme s'il s'agissait de fonctions: passez-les à d'autres méthodes / fonctions et appelez-les. Pour ce faire, la __call__
fonction de classe doit être spécialisée.
def __call__(self, [args ...])
Il prend en entrée un nombre variable d'arguments. En supposant x
être une instance de la classe X
, cela x.__call__(1, 2)
revient à appeler x(1,2)
ou l'instance elle-même en tant que fonction .
En Python, __init__()
est correctement défini comme constructeur de classe (tout comme __del__()
le destructeur de classe). Par conséquent, il y a une nette distinction entre __init__()
et __call__()
: le premier crée une instance de Class up, le second rend cette instance appelable comme une fonction sans impact sur le cycle de vie de l'objet lui-même (c'est __call__
-à- dire sans impact sur le cycle de vie de construction / destruction) mais il peut modifier son état interne (comme illustré ci-dessous).
Exemple.
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
def __call__
simplement par def update
, nous donnons à la classe une update
méthode qui fait la même chose. Il peut désormais également modifier l'état interne, s'il est appelé ci-dessous comme s.update(7, 8)
. Alors, c'est __call__
juste du sucre syntaxique alors?
__call__
rend l'instance d'une classe appelable. Pourquoi serait-il nécessaire?
Techniquement, il __init__
est appelé une fois __new__
lorsque l'objet est créé, afin qu'il puisse être initialisé.
Mais il existe de nombreux scénarios où vous voudrez peut-être redéfinir votre objet, disons que vous en avez terminé avec votre objet et que vous pourriez avoir besoin d'un nouvel objet. Avec, __call__
vous pouvez redéfinir le même objet comme s'il était nouveau.
Ce n'est qu'un cas, il peut y en avoir beaucoup plus.
>>> 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 ...
>>>
__init__
serait traité comme un constructeur où les __call__
méthodes peuvent être appelées avec des objets un certain nombre de fois. Les fonctions __init__
et __call__
acceptent les arguments par défaut.
__init__
n'est pas une fonction constructeur mais l' __new__
est. __init__
est appelé juste après__new__
__new__
crée l'instance de classe et recevoir une classe comme argument, alors que __init__
le constructeur d'instance qui est la raison pour laquelle il reçoit self
. Un moyen simple de voir cela est dans l'appel a = Foo(1,2,3)
la fonction qui recevra les arguments du constructeur __init__
.
Je vais essayer d'expliquer cela à l'aide d'un exemple, supposons que vous vouliez imprimer un nombre fixe de termes de la série fibonacci. N'oubliez pas que les 2 premiers termes de la série fibonacci sont 1s. Par exemple: 1, 1, 2, 3, 5, 8, 13 ....
Vous voulez que la liste contenant les numéros de fibonacci ne soit initialisée qu'une seule fois et ensuite elle devrait être mise à jour. Maintenant, nous pouvons utiliser la __call__
fonctionnalité. Lisez la réponse de @mudit verma. C'est comme si vous vouliez que l'objet soit appelable en tant que fonction mais pas réinitialisé à chaque fois que vous l'appeliez.
Par exemple:
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 sortie est:
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 vous observez que la sortie a __init__
été appelée une seule fois, c'est à ce moment que la classe a été instanciée pour la première fois, l'objet a ensuite été appelé sans réinitialisation.
Vous pouvez également utiliser la __call__
méthode en faveur de la mise en œuvre de décorateurs .
Cet exemple tiré de Python 3 Patterns, Recipes and Idioms
class decorator_without_arguments(object):
def __init__(self, f):
"""
If there are no decorator arguments, the function
to be decorated is passed to the constructor.
"""
print("Inside __init__()")
self.f = f
def __call__(self, *args):
"""
The __call__ method is not called until the
decorated function is called.
"""
print("Inside __call__()")
self.f(*args)
print("After self.f( * args)")
@decorator_without_arguments
def sayHello(a1, a2, a3, a4):
print('sayHello arguments:', a1, a2, a3, a4)
print("After decoration")
print("Preparing to call sayHello()")
sayHello("say", "hello", "argument", "list")
print("After first sayHello() call")
sayHello("a", "different", "set of", "arguments")
print("After second sayHello() call")
Sortie :
Ainsi, __init__
est appelé lorsque vous créez une instance de n'importe quelle classe et initialisez également la variable d'instance.
Exemple:
class User:
def __init__(self,first_n,last_n,age):
self.first_n = first_n
self.last_n = last_n
self.age = age
user1 = User("Jhone","Wrick","40")
Et __call__
est appelé lorsque vous appelez l'objet comme n'importe quelle autre fonction.
Exemple:
class USER:
def __call__(self,arg):
"todo here"
print(f"I am in __call__ with arg : {arg} ")
user1=USER()
user1("One") #calling the object user1 and that's gonna call __call__ dunder functions
__init__
est une méthode spéciale dans les classes Python, c'est la méthode constructeur d'une classe. Il est appelé chaque fois qu'un objet de la classe est construit ou on peut dire qu'il initialise un nouvel objet. Exemple:
In [4]: class A:
...: def __init__(self, a):
...: print(a)
...:
...: a = A(10) # An argument is necessary
10
Si nous utilisons A (), cela donnera une erreur
TypeError: __init__() missing 1 required positional argument: 'a'
car il nécessite 1 argument à a
cause de __init__
.
........
__call__
lorsqu'il est implémenté dans la classe nous aide à appeler l'instance de classe en tant qu'appel de fonction.
Exemple:
In [6]: class B:
...: def __call__(self,b):
...: print(b)
...:
...: b = B() # Note we didn't pass any arguments here
...: b(20) # Argument passed when the object is called
...:
20
Ici, si nous utilisons B (), il fonctionne très bien car il n'a pas de __init__
fonction ici.
__call__
permet de renvoyer des valeurs arbitraires, tout en __init__
étant un constructeur retourne implicitement l'instance de classe. Comme d'autres réponses l'ont correctement souligné, __init__
est appelé une seule fois, alors qu'il est possible d'appeler __call__
plusieurs fois, au cas où l'instance initialisée est affectée à une variable intermédiaire.
>>> class Test:
... def __init__(self):
... return 'Hello'
...
>>> Test()
Traceback (most recent call last):
File "<console>", line 1, in <module>
TypeError: __init__() should return None, not 'str'
>>> class Test2:
... def __call__(self):
... return 'Hello'
...
>>> Test2()()
'Hello'
>>>
>>> Test2()()
'Hello'
>>>
Des réponses courtes et douces sont déjà fournies ci-dessus. Je veux fournir une implémentation pratique par rapport à Java.
class test(object):
def __init__(self, a, b, c):
self.a = a
self.b = b
self.c = c
def __call__(self, a, b, c):
self.a = a
self.b = b
self.c = c
instance1 = test(1, 2, 3)
print(instance1.a) #prints 1
#scenario 1
#creating new instance instance1
#instance1 = test(13, 3, 4)
#print(instance1.a) #prints 13
#scenario 2
#modifying the already created instance **instance1**
instance1(13,3,4)
print(instance1.a)#prints 13
Remarque : le scénario 1 et le scénario 2 semblent identiques en termes de sortie de résultats. Mais dans le scénario 1, nous créons à nouveau une autre instance1 nouvelle instance . Dans le scénario 2, nous modifions simplement l' instance1 déjà créée . __call__
est bénéfique ici car le système n'a pas besoin de créer de nouvelle instance.
Équivalent en Java
public class Test {
public static void main(String[] args) {
Test.TestInnerClass testInnerClass = new Test(). new TestInnerClass(1, 2, 3);
System.out.println(testInnerClass.a);
//creating new instance **testInnerClass**
testInnerClass = new Test().new TestInnerClass(13, 3, 4);
System.out.println(testInnerClass.a);
//modifying already created instance **testInnerClass**
testInnerClass.a = 5;
testInnerClass.b = 14;
testInnerClass.c = 23;
//in python, above three lines is done by testInnerClass(5, 14, 23). For this, we must define __call__ method
}
class TestInnerClass /* non-static inner class */{
private int a, b,c;
TestInnerClass(int a, int b, int c) {
this.a = a;
this.b = b;
this.c = c;
}
}
}
Nous pouvons utiliser la méthode d' appel pour utiliser d'autres méthodes de classe comme méthodes statiques.
class _Callable:
def __init__(self, anycallable):
self.__call__ = anycallable
class Model:
def get_instance(conn, table_name):
""" do something"""
get_instance = _Callable(get_instance)
provs_fac = Model.get_instance(connection, "users")
__init__
méthode est utilisée lorsque la classe est appelée pour initialiser l'instance, tandis que la__call__
méthode est appelée lorsque l' instance est appelée