class Singleton(type):
def __init__(self, *args, **kwargs):
print 'calling __init__ of Singleton class', self
print 'args: ', args
print 'kwargs: ', kwargs
super(Singleton, self).__init__(*args, **kwargs)
self.__instance = None
def __call__(self, *args, **kwargs):
print 'running __call__ of Singleton', self
print 'args: ', args
print 'kwargs: ', kwargs, '\n\n'
if self.__instance is None:
self.__instance = super(Singleton, self).__call__(*args, **kwargs)
return self.__instance
class A(object):
__metaclass__ = Singleton
def __init__(self,a):
print 'in __init__ of A: ', self
self.a = a
print 'self.a: ', self.a
a=A(10)
b=A(20)
I copied this code from Ben’s answer to the question Python's use of __new__ and __init__? and modified it a little. But, I am not aware of the flow. Although I understand from a higher level what this code is intended to do. But, internally how it works, I am not quite sure of.
I get the following output when running this code:-
calling __init__ of Singleton class <class '__main__.A'>
args: ('A', (<type 'object'>,), {'__module__': '__main__', '__metaclass__': <class '__main__.Singleton'>, '__init__': <function __init__ at 0x01F9F7B0>})
kwargs: {}
running __call__ of Singleton <class '__main__.A'>
args: (10,)
kwargs: {}
in __init__ of A: <__main__.A object at 0x01FA7A10>
self.a: 10
running __call__ of Singleton <class '__main__.A'>
args: (20,)
kwargs: {}
I cant understand how the args and kwargs for __init__ and __call__ become different.
While using metaclasses, this link (What is a metaclass in Python?) has explained how to use __new__ and a function as a metaclass. But, I do not understand how __call__ is being used.
Can somebody explain the flow? By this, I mean, the precedence in which __new__, __call__, __init__ are called and who calls them?
Your code doesn’t include any
__new__, so little can be said about it.But you create a metaclass which is instantiated at the time class
Ais created. In other words, the classAis an object itself and as such an instance of its metaclassSingleton.So let’s look what happens:
After
A‘s environment is finished (its methods exist, its dict exists as well, …), the class gets created as an instance of the metaclass. Essentially, the call iswhere
<the dict>is the dict containing the class’s namespace (here:__module__,__metaclass__and__init__).On this call to
Singleton, callingsuper(Singleton, self).__call__(*args, **kwargs)results in calling the__new__method which returns a new instance, on which.__init__is called afterwards.That’s why this happens:
After
Ais constructed, you use it by instantiating it:This calls
A.Ais an instance ofSingleton, soSingleton.__call__is invoked – with the effect you see:Singleton.__call__callstype.__call__, this callsA.__new__andA.__init__:Then you do
which calls
Singleton.__call__:Here the
supercall is suppressed and the old object is returned.