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)
我从Ben对问题Python's use of __new__ and __init__?的回答中复制了这段代码并对其进行了一些修改。但是,我不知道这个流程。虽然我从更高层次了解此代码的目的是什么。但是,在内部如何运作,我不太确定。
运行此代码时,我得到以下输出: -
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: {}
我无法理解args
和kwargs
的{{1}}和__init__
如何变得不同。
在使用元类时,此链接(What is a metaclass in Python?)已经解释了如何使用__call__
和函数作为元类。但是,我不明白__new__
是如何被使用的。
有人可以解释这个流程吗?我的意思是,这是__call__
,__new__
,__call__
被调用以及谁调用它们的优先顺序?
答案 0 :(得分:8)
您的代码不包含任何__new__
,因此对它的描述很少。
但是你创建了一个元类,它在创建类A
时被实例化。换句话说,类A
本身就是一个对象,并且是其元类Singleton
的实例。
让我们来看看会发生什么:
在A
的环境完成后(其方法存在,其dict也存在,...),该类被创建为元类的实例。基本上,电话是
A = Singleton('A', (object,), <the dict>)
其中<the dict>
是包含类名称空间的dict(此处为:__module__
,__metaclass__
和__init__
)。
在拨打Singleton
时,调用super(Singleton, self).__call__(*args, **kwargs)
会调用__new__
方法,该方法会返回一个新实例,之后会调用.__init__
。
这就是为什么会发生这种情况:
calling __init__ of Singleton class <class '__main__.A'>
args: ('A', (<type 'object'>,), {'__module__': '__main__', '__metaclass__': <class '__main__.Singleton'>, '__init__': <function __init__ at 0x01F9F7B0>})
kwargs: {}
构造A
之后,通过实例化它来使用它:
a = A(10)
这会调用A
。 A
是Singleton
的一个实例,因此调用Singleton.__call__
- 具有您看到的效果:
running __call__ of Singleton <class '__main__.A'>
args: (10,)
kwargs: {}
Singleton.__call__
来电type.__call__
,这会调用A.__new__
和A.__init__
:
in __init__ of A: <__main__.A object at 0x01FA7A10>
self.a: 10
然后你做
b = A(20)
调用Singleton.__call__
:
running __call__ of Singleton <class '__main__.A'>
args: (20,)
kwargs: {}
此处super
调用被禁止,并返回旧对象。