Tôi có một trường hợp sử dụng kỳ lạ và khác thường đối với metaclasses nơi tôi muốn thay đổi __metaclass__
của một lớp cơ sở sau khi nó được định nghĩa để các lớp con của nó sẽ tự động sử dụng __metaclass__
mới. Nhưng điều đó kỳ quặc không hoạt động:Tại sao tôi không thể thay đổi thuộc tính __metaclass__ của một lớp?
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)
Những gì tôi đang làm rất tốt có thể không khôn ngoan/không được hỗ trợ/không xác định, nhưng tôi có thể không cho cuộc sống của tôi ra như thế nào metaclass cũ đang được gọi, và tôi ít nhất cũng hiểu được điều đó là có thể.
EDIT: Dựa trên một gợi ý do jsbueno
, tôi thay thế dòng Foo.__metaclass__ = MetaSub
với dòng sau, mà đã làm chính xác những gì tôi muốn:
Foo = type.__new__(MetaSub, "Foo", Foo.__bases__, dict(Foo.__dict__))
Cảm ơn bạn đã không làm chính xác những gì tôi muốn, vì tôi vẫn muốn các lớp con của 'Foo' có metaclass, nhưng tôi đã chỉnh sửa câu hỏi của mình để bao gồm giải pháp đã làm những gì tôi cần, dựa trên gợi ý. –