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__
?
Yes - it's up to
Meta.__call__
to callProductClass.__init__
(or not, as the case may be).To quote the documentation:
That page also mentions a scenario where the metaclass's
__call__
may return an instance of a different class (i.e. notProductClass
in your example). In this scenario it would clearly be inappropriate to callProductClass.__init__
automatically.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: