What is the difference between __init__ and __call__? What is the difference between __init__ and __call__? python python

What is the difference between __init__ and __call__?

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()initIn [3]: a()call

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


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.x1>>> s(7, 8)__call__ with (7,8)>>> s.x7