元类的 “__call__” 和产品类的 “__init__”
问题描述:
说我有一个元类:元类的 “__call__” 和产品类的 “__init__”
class Meta(type):
def __call__(cls, *args):
print "Meta: __call__ with", args
class ProductClass(object):
__metaclass__ = Meta
def __init__(self, *args):
print "ProductClass: __init__ with", args
p = ProductClass(1)
输出如下:
Meta: __call__ with (1,)
问:
为什么不ProductClass的__init__
已触发? 仅仅因为Meta的__call__
?
UPDATE:
现在,我想补充__new__
为ProductClass:
class ProductClass(object):
__metaclass__ = Meta
def __new__(cls, *args):
print "ProductClass: __new__ with", args
return super(ProductClass, cls).__new__(cls, *args)
def __init__(self, *args):
print "ProductClass: __init__ with", args
p = ProductClass(1)
它是多彩的__call__
的责任,呼吁ProductClass的__new__
和__init__
?
答
是的 - 这是Meta.__call__
拨打ProductClass.__init__
(或不是,视情况而定)。
例如限定元类 定制
__call__()
方法允许自定义行为当类被调用时,例如并不总是 创建一个新的实例。
该页面还提到一种情况,元类的__call__
可能会返回一个不同的类的实例(即不ProductClass
在你的例子)。在这种情况下,自动呼叫ProductClass.__init__
显然不合适。
答
有延伸的方法和覆盖它,你只是在你的元类Meta
没有叫,因为你定义了__call__
方法和你没有调用父__call__
首要之间的OOP的差异。有你想你必须扩展__call__
方法通过调用父类的方法行为:
class Meta(type):
def __call__(cls, *args):
print "Meta: __call__ with", args
return super(Meta, cls).__call__(*args)
什么,如果我得到了一个ProductClass“__new__”? Meta的“__call__”调用ProductClass的“__new__”和“__init__”?看我的更新。 – Alcott
显然,Meta的“__call__”在ProductClass的“__new__”之前被首先调用。 – Alcott
问题是,需要'Meta .__ call__'来调用'ProductClass .__ new__'和'ProductClass .__ init__'。通常,'type .__ call__'是为你做的,但是当你定义'Meta .__ call__'时,你会覆盖这个行为,这意味着除非你这么做,否则它不会被执行。所以,你需要自己调用'__new__'和'__init__',或者调用类似'.__ call __(cls,* args)'的东西。 –