У меня есть странный и необычный вариант использования для метаклассов, где я хотел бы изменить __metaclass__
базового класса после его определения, чтобы его подклассы автоматически использовали новый __metaclass__
. Но это странно не работает:
class MetaBase(type):
def __new__(cls, name, bases, attrs):
attrs["y"] = attrs["x"] + 1
return type.__new__(cls, name, bases, attrs)
class Foo(object):
__metaclass__ = MetaBase
x = 5
print (Foo.x, Foo.y) # prints (5, 6) as expected
class MetaSub(MetaBase):
def __new__(cls, name, bases, attrs):
attrs["x"] = 11
return MetaBase.__new__(cls, name, bases, attrs)
Foo.__metaclass__ = MetaSub
class Bar(Foo):
pass
print(Bar.x, Bar.y) # prints (5, 6) instead of (11, 12)
То, что я делаю, вполне может быть неразумным / неподдерживаемым / неопределенным, но я не могу понять, как вызывается старый метакласс, и мне хотелось бы хотя бы понять, как это возможно.
РЕДАКТИРОВАТЬ: Основываясь на предложении jsbueno
, я заменил строку Foo.__metaclass__ = MetaSub
следующей строкой, которая сделала именно то, что я хотел:
Foo = type.__new__(MetaSub, "Foo", Foo.__bases__, dict(Foo.__dict__))