当我学习__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__
类,是吗?
这是我从日志中可以看到的,有什么我想念的吗?
答案 0 :(得分:3)
1)正确 - 主要是 - 元类的__call__
(在这种情况下,__call__
的超级类metaclass
是type
)调用{来自实例的{1}}和__init__
。
2)通过省略传递到元类的超级__new__
,你可以将你的kwargs抛给实例的__init__
和__new__
。元类' __call__
负责调用实例__call__
和__new__
。
旁注:使用Python 3 - 深入了解Python 2.x以前的工作原理是没有意义的 - 自上次发布Python 2以来已经过去了7年,距离它已经过去3年了行结束。 (虽然您正在调查的过程没有改变,但是对于声明元类的方式 - 但是什么给了我" auf,这是旧的"是带参数的__init__