需要了解__init __,__ new__和__call__的流程

时间:2012-10-19 09:49:38

标签: python design-patterns singleton metaclass

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:  {}

我无法理解argskwargs的{​​{1}}和__init__如何变得不同。 在使用元类时,此链接(What is a metaclass in Python?)已经解释了如何使用__call__和函数作为元类。但是,我不明白__new__是如何被使用的。

有人可以解释这个流程吗?我的意思是,这是__call____new____call__被调用以及谁调用它们的优先顺序?

1 个答案:

答案 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)

这会调用AASingleton的一个实例,因此调用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调用被禁止,并返回旧对象。