Я писал метакласс и случайно сделал это как это:
class MetaCls(type):
def __new__(cls, name, bases, dict):
return type(name, bases, dict)
... вместо подобного это:
class MetaCls(type):
def __new__(cls, name, bases, dict):
return type.__new__(cls, name, bases, dict)
Каково точно различие между этими двумя метаклассами? И более конкретно, что заставило первый не работать правильно (в некоторые классы не назвал метакласс)?
В первом примере вы создаете совершенно новый класс:
>>> class MetaA(type):
... def __new__(cls, name, bases, dct):
... print 'MetaA.__new__'
... return type(name, bases, dct)
... def __init__(cls, name, bases, dct):
... print 'MetaA.__init__'
...
>>> class A(object):
... __metaclass__ = MetaA
...
MetaA.__new__
>>>
, а во втором случае вы вызываете родительский __ new __
:
>>> class MetaA(type):
... def __new__(cls, name, bases, dct):
... print 'MetaA.__new__'
... return type.__new__(cls, name, bases, dct)
... def __init__(cls, name, bases, dct):
... print 'MetaA.__init__'
...
>>> class A(object):
... __metaclass__ = MetaA
...
MetaA.__new__
MetaA.__init__
>>>
return type(name, bases, dict)
В результате вы получите новый тип
, а не экземпляр MetaCls
вообще. Следовательно, ваши методы, определенные в MetaCls
(включая __ init __
), не могут быть вызваны.
type .__ new __
будет вызываться как часть создания этого нового типа, да, но значение cls
, входящее в эту функцию, будет type
, а не Метаклипы
.
Все это довольно хорошо описано здесь .
Если вы не вернете объект правильного типа, нет смысла определять собственный метакласс.