У меня есть странный и необычный прецедент для метаклассов, где я хотел бы изменить __metaclass__
базового класса после того, как он будет определен таким образом, чтобы его подклассы автоматически использовали новый __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)
Что я делаю очень хорошо может быть неразумным/неподдерживаемый/не определено, но я не могу за жизнь мне понять, как старый метакласс быть вызван, и я хотел бы по крайней мере понять, как это возможно.
EDIT: на основе предложений, сделанных jsbueno
, я заменил строку Foo.__metaclass__ = MetaSub
со следующей строкой, которая делала именно то, что я хотел:
Foo = type.__new__(MetaSub, "Foo", Foo.__bases__, dict(Foo.__dict__))
Спасибо за подсказку, что не сделал именно то, что я хотел, так как я все еще хочу, чтобы подклассы «Foo» имели метакласс, но я отредактировал свой вопрос, чтобы включить решение, которое делало то, что мне нужно, на основе вашего предложение. –