I want to know the difference between __init__
and __call__
methods.
For example:
class test:
def __init__(self):
self.a = 10
def __call__(self):
b = 20
The first is used to initialise newly created object, and receives arguments used to do that:
class Foo:
def __init__(self, a, b, c):
# ...
x = Foo(1, 2, 3) # __init__
The second implements function call operator.
class Foo:
def __call__(self, a, b, c):
# ...
x = Foo()
x(1, 2, 3) # __call__
Defining a custom __call__()
method in the meta-class allows the class's instance to be called as a function, not always modifying the instance itself.
In [1]: class A:
...: def __init__(self):
...: print "init"
...:
...: def __call__(self):
...: print "call"
...:
...:
In [2]: a = A()
init
In [3]: a()
call
__call__
not only allows an instance to be used as a function ... it defines the function body that's executed when an instance is used as a function.
In Python, functions are first-class objects, this means: function references can be passed in inputs to other functions and/or methods, and executed from inside them.
Instances of Classes (aka Objects), can be treated as if they were functions: pass them to other methods/functions and call them. In order to achieve this, the __call__
class function has to be specialized.
def __call__(self, [args ...])
It takes as an input a variable number of arguments. Assuming x
being an instance of the Class X
, x.__call__(1, 2)
is analogous to calling x(1,2)
or the instance itself as a function.
In Python, __init__()
is properly defined as Class Constructor (as well as __del__()
is the Class Destructor). Therefore, there is a net distinction between __init__()
and __call__()
: the first builds an instance of Class up, the second makes such instance callable as a function would be without impacting the lifecycle of the object itself (i.e. __call__
does not impact the construction/destruction lifecycle) but it can modify its internal state (as shown below).
Example.
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__
simply with def update
, we give the class an update
method that does the same thing. It can now also modify the internal state, if called below as s.update(7, 8)
. So, is __call__
just syntactix sugar then?
__init__
, so luckily it doesn't break the class construction.
__call__
makes the instance of a class callable. Why would it be required?
Technically __init__
is called once by __new__
when object is created, so that it can be initialized.
But there are many scenarios where you might want to redefine your object, say you are done with your object, and may find a need for a new object. With __call__
you can redefine the same object as if it were new.
This is just one case, there can be many more.
>>> 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__
would be treated as Constructor where as __call__
methods can be called with objects any number of times. Both __init__
and __call__
functions do take default arguments.
__init__
is not a constructor function but __new__
is. __init__
is called right after __new__
__new__
creates the class instance and receive a class as argument, whereas __init__
is the instance constructor which is why it receives self
. An easy way to see this is in the call a = Foo(1,2,3)
the function that will receive the constructor arguments will be __init__
.
I will try to explain this using an example, suppose you wanted to print a fixed number of terms from fibonacci series. Remember that the first 2 terms of fibonacci series are 1s. Eg: 1, 1, 2, 3, 5, 8, 13....
You want the list containing the fibonacci numbers to be initialized only once and after that it should update. Now we can use the __call__
functionality. Read @mudit verma's answer. It's like you want the object to be callable as a function but not re-initialized every time you call it.
Eg:
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)
The output is:
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__
If you observe the output __init__
was called only one time that's when the class was instantiated for the first time, later on the object was being called without re-initializing.
__call__
allows to return arbitrary values, while __init__
being an constructor returns the instance of class implicitly. As other answers properly pointed out, __init__
is called just once, while it's possible to call __call__
multiple times, in case the initialized instance is assigned to intermediate variable.
>>> 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'
>>>
So, __init__
is called when you are creating an instance of any class and initializing the instance variable also.
Example:
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")
And __call__
is called when you call the object like any other function.
Example:
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
You can also use __call__
method in favor of implementing decorators.
This example taken from 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")
Output:
https://i.stack.imgur.com/IzNSh.png
Case 1:
class Example:
def __init__(self, a, b, c):
self.a=a
self.b=b
self.c=c
print("init", self.a, self.b, self.c)
Run:
Example(1,2,3)(7,8,9)
Result:
- init 1 2 3
- TypeError: 'Example' object is not callable
Case 2:
class Example:
def __init__(self, a, b, c):
self.a=a
self.b=b
self.c=c
print("init", self.a, self.b, self.c)
def __call__(self, x, y, z):
self.x=x
self.y=y
self.z=z
print("call", self.x, self.y, self.z)
Run:
Example(1,2,3)(7,8,9)
Result:
- init 1 2 3
- call 7 8 9
Short and sweet answers are already provided above. I wanna provide some practical implementation as compared with 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
Note: scenario 1 and scenario 2 seems same in terms of result output. But in scenario1, we again create another new instance instance1. In scenario2, we simply modify already created instance1. __call__
is beneficial here as the system doesn't need to create new instance.
Equivalent in 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;
}
}
}
__init__
is a special method in Python classes, it is the constructor method for a class. It is called whenever an object of the class is constructed or we can say it initialises a new object. Example:
In [4]: class A:
...: def __init__(self, a):
...: print(a)
...:
...: a = A(10) # An argument is necessary
10
If we use A(), it will give an error TypeError: __init__() missing 1 required positional argument: 'a'
as it requires 1 argument a
because of __init__
.
........
__call__
when implemented in the Class helps us invoke the Class instance as a function call.
Example:
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
Here if we use B(), it runs just fine because it doesn't have an __init__
function here.
We can use call method to use other class methods as static methods.
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")
call method is used to make objects act like functions.
>>> 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
<*There is no __call__ method so it doesn't act like function and throws error.*>
>>>
>>> class B:
... def __init__(self):
... print "From init ... "
... def __call__(self):
... print "From call it is a function ... "
...
>>> b = B()
From init ...
>>> b()
From call it is a function...
>>>
<* __call__ method made object "b" to act like function *>
We can also pass it to a class variable.
class B:
a = A()
def __init__(self):
print "From init ... "
Success story sharing
__init__
method is used when the class is called to initialize the instance, while the__call__
method is called when the instance is called__call__
?__call__
can return an arbitrary value, whereas__init__
must return None.