Relationship of metaclass's “__call__” and instance's “__init__”?

让人想犯罪 __ 提交于 2019-12-21 04:42:08

问题


Say I've got a metaclass and a class using it:

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)

Output as follows:

Meta: __call__ with (1,)

Question:

Why isn't ProductClass.__init__ triggered...just because of Meta.__call__?

UPDATE:

Now, I add __new__ for 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)

Is it Meta.__call__'s responsibility to call ProductClass's __new__ and __init__?


回答1:


There is a difference in OOP between extending a method and overriding it, what you just did in your metaclass Meta is called overriding because you defined your __call__ method and you didn't call the parent __call__. to have the behavior that you want you have to extend __call__ method by calling the parent method:

class Meta(type):
    def __call__(cls, *args):
        print "Meta: __call__ with", args
        return super(Meta, cls).__call__(*args)



回答2:


Yes - it's up to Meta.__call__ to call ProductClass.__init__ (or not, as the case may be).

To quote the documentation:

for example defining a custom __call__() method in the metaclass allows custom behavior when the class is called, e.g. not always creating a new instance.

That page also mentions a scenario where the metaclass's __call__ may return an instance of a different class (i.e. not ProductClass in your example). In this scenario it would clearly be inappropriate to call ProductClass.__init__ automatically.



来源:https://stackoverflow.com/questions/7485324/relationship-of-metaclasss-call-and-instances-init

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!