说我有一个元类和一个使用它的类:
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__
?
更新
现在,我为ProductClass添加__new__
:
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)
Meta.__call__
是否有责任致电ProductClass的__new__
和__init__
?
答案 0 :(得分:7)
扩展方法和覆盖方法之间的OOP存在差异,您在元类Meta
中刚刚执行的操作被称为覆盖,因为您定义了__call__
方法并且没有调用父方法__call__
。通过调用父方法来获得您希望必须扩展__call__
方法的行为:
class Meta(type):
def __call__(cls, *args):
print "Meta: __call__ with", args
return super(Meta, cls).__call__(*args)
答案 1 :(得分:4)
是的 - 最多Meta.__call__
可以致电ProductClass.__init__
(或不是,视具体情况而定)。
例如,在元类中定义自定义
__call__()
方法 允许在调用类时的自定义行为,例如不总是 创建一个新实例。
该页面还提到了一个场景,即元类的__call__
可能会返回不同类的实例(例如,在您的示例中不是ProductClass
)。在这种情况下,自动调用ProductClass.__init__
显然是不合适的。