python对象创建过程的细节是什么?

时间:2017-03-28 02:36:48

标签: python metaclass

当我学习__int____new____call__和python的元类时,我对以下代码感到困惑:

class MyMeta(type):
    def __init__(cls, name, bases, attr):
        print 'enter MyMeta'
        super(MyMeta, cls).__init__(name, bases, attr)
        print 'leave MyMeta'

    def __call__(cls, *args, **kwargs):
        print 'enter MyMeta __call__'
        instance = super(MyMeta, cls).__call__(*args, **kwargs)
        print 'leave MyMeta __call__'
        return instance


class MyObj(object):
    __metaclass__ = MyMeta

    def __init__(self, *args, **kwargs):
        print 'enter MyObj __init__'
        super(MyObj, self).__init__()
        self.aaa = args[0]
        self.kw = kwargs
        print self.aaa, self.kw
        print 'leave MyObj __init__'

    def __new__(cls, *args, **kwargs):
        print 'enter MyObj __new__'
        instance = super(MyObj, cls).__new__(cls, *args, **kwargs)
        print 'leave MyObj __new__'
        return instance

obj = MyObj(123, k=456)

,输出为:

enter MyMeta            #L1
leave MyMeta            #L2
enter MyMeta __call__   #L3
enter MyObj __new__     #L4
leave MyObj __new__     #L5
enter MyObj __init__    #L6
123 {'k': 456}          #L7
leave MyObj __init__    #L8
leave MyMeta __call__   #L9

我的问题是:

1,创建对象时,进程为__call__ metacall,然后是__new____init__类,是吗?

这是我从日志中可以看到的,有什么我想念的吗?

1 个答案:

答案 0 :(得分:3)

1)正确 - 主要是 - 元类的__call__(在这种情况下,__call__的超级类metaclasstype)调用{来自实例的{1}}和__init__

2)通过省略传递到元类的超级__new__,你可以将你的kwargs抛给实例的__init____new__。元类' __call__负责调用实例__call____new__

旁注:使用Python 3 - 深入了解Python 2.x以前的工作原理是没有意义的 - 自上次发布Python 2以来已经过去了7年,距离它已经过去3年了行结束。 (虽然您正在调查的过程没有改变,但是对于声明元类的方式 - 但是什么给了我" auf,这是旧的"是带参数的__init__