需要了解__init__,__new__和__call__的流程 [英] need to understand the flow of __init__, __new__ and __call__

查看:84
本文介绍了需要了解__init__,__new__和__call__的流程的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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对__new__和__init__的使用中复制了这段代码? 并对其进行了一些修改.但是,我不知道流程.尽管我从更高的层次上了解了此代码的用途.但是,从内部来看,我不太确定.

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

我无法理解__init____call__argskwargs如何变得不同. 使用元类时,此链接(什么是Python中的元类?)具有解释了如何使用__new__和一个函数作为元类.但是,我不了解__call__的使用方式.

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.

有人可以解释流程吗?我的意思是说,__new____call____init__被调用的优先级以及谁调用它们?

Can somebody explain the flow? By this, I mean, the precedence in which __new__, __call__, __init__ are called and who calls them?

推荐答案

您的代码不包含任何__new__,因此对此一无所知.

Your code doesn't include any __new__, so little can be said about it.

但是您创建一个元类,该元类在创建类A时实例化.换句话说,类A本身就是对象,因此是其元类Singleton的实例.

But you create a metaclass which is instantiated at the time class A is created. In other words, the class A is an object itself and as such an instance of its metaclass Singleton.

让我们看看会发生什么:

So let's look what happens:

A的环境完成后(其方法存在,其dict也存在,...),该类被创建为元类的实例.本质上,呼叫是

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 is

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

其中<the dict>是包含类名称空间(此处为__module____metaclass____init__)的字典.

where <the dict> is the dict containing the class's namespace (here: __module__, __metaclass__ and __init__).

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

On this call to Singleton, calling super(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:

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

After A is constructed, you use it by instantiating it:

a = A(10)

这将调用A. ASingleton的实例,因此会调用Singleton.__call__.效果如下:

This calls A. A is an instance of Singleton, so Singleton.__call__ is invoked – with the effect you see:

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调用被禁止,并且旧对象被返回.

Here the super call is suppressed and the old object is returned.

这篇关于需要了解__init__,__new__和__call__的流程的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆