Metaclass не вызывается в подклассах

вот сеанс python.

>>> class Z(type):
    def __new__(cls, name, bases, attrs):
        print cls
        print name
        return type(name, bases, attrs)
...     
>>> class Y(object):
    __metaclass__ = Z
...     
<class '__main__.Z'>
Y
>>> class X(Y):
...     pass
... 
>>> class W(Y):
...     __metaclass__ = Z
...     
<class '__main__.Z'>
W
>>> 

после определения класса X я ожидаю, что Z._new__ будет вызван для него и напечатает две строки, чего не происходит (как метакласс наследуются?)

1 ответов


проблема в том, что cls аргумент (который является объектом metaclass) не передается при вызове type, поэтому объект класса Y то, что создано и возвращено, не имеет никакой ссылки на metaclass Z.

если вы замените последнюю строку __new__ С

return super(Z, cls).__new__(cls, name, bases, attrs)

тогда это работает. Обратите внимание, что хотя cls используется super мы все еще должны обеспечить cls в качестве аргумента, поскольку super здесь возвращает несвязанный метод (см. здесь для более).

в качестве альтернативы использованию super можно использовать:

 return type.__new__(cls, name, bases, attrs)

важно то, что мы даем cls (наш объект метакласса Z) в classmethod __new__. Более короткая форма type(name, bases, attrs) заполняет на cls аргумент, который, конечно, неверен. Эта ошибка похожа на вызов метода экземпляра с неправильным