关于python:需要了解__init __,__ new__和__call__的流程

need to understand the flow of __init__, __new__ and __call__

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
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, '

'

        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)

我把这段代码从本的答案复制到了python使用"new"和"init"这个问题上。修改了一下。但是,我不知道流动。尽管我从更高的层次上理解了这段代码的目的。但是,从内部来说,它是如何工作的,我不太确定。

运行此代码时,我得到以下输出:

1
2
3
4
5
6
7
8
9
10
11
12
13
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__init____call__的区别。使用元类时,此链接(什么是Python中的元类?)解释了如何使用__new__和函数作为元类。但是,我不明白__call__是如何被使用的。

有人能解释一下流程吗?我的意思是,在这种情况下,调用__new____call____init__的优先级是谁?


您的代码不包括任何__new__,因此对此几乎无话可说。

但是您创建了一个元类,它在创建类A时被实例化。换句话说,类A是一个对象本身,也是它的元类Singleton的一个实例。

让我们看看会发生什么:

A的环境完成后(它的方法存在,它的dict也存在,…),类被创建为元类的一个实例。从本质上讲,呼叫是

1
A = Singleton('A', (object,), <the dict>)

其中是包含类名称空间的dict(此处:__module____metaclass____init__)。

在调用Singleton时,调用super(Singleton, self).__call__(*args, **kwargs)会导致调用__new__方法,该方法返回一个新实例,随后在该实例上调用.__init__

这就是为什么会发生这种情况:

1
2
3
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之后,您可以通过实例化它来使用它:

1
a = A(10)

这叫AASingleton的实例,因此调用Singleton.__call__,效果如下:

1
2
3
running __call__ of Singleton <class '__main__.A'>
args:  (10,)
kwargs:  {}

Singleton.__call__type.__call__,此称A.__new__A.__init__

1
2
in __init__ of A:   <__main__.A object at 0x01FA7A10>
self.a:  10

然后你这样做

1
b = A(20)

称为Singleton.__call__

1
2
3
running __call__ of Singleton <class '__main__.A'>
args:  (20,)
kwargs:  {}

这里抑制super调用,返回旧对象。