我已经看到了允许在运行时添加基类的问题,但我有一个更具体的问题,试图通过使用元类在更深层次结构中添加基类。
class Meta(type):
def __call__(cls, *args, special=False, **kwargs):
if special:
cls = cls.__class__(cls.__name__ + Special.__name__, (Special,), {})
return super(Meta, cls).__call__(*args, **kwargs)
class Base(metaclass=Meta):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
print('construct Base')
class Special(Base):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
print('construct Special')
class Concrete(Base):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
print('construct Concrete')
class Specific(Concrete):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
print('construct Specific')
c = Specific(special=True)
print(c.__class__.__mro__) # (Specific, Special, Base, Object)
# construct Base
# construct Special
# (<class 'SpecificSpecial'>, <class 'Special'>, <class 'Base'>, <class 'object'>)
我希望能够在运行时在元类Special
函数中将__call__
类添加到我的层次结构中。但这会覆盖Concrete
基类,基本上会将其删除。我不确定如何正确插入此基础。此外,在尝试创建新类时,我丢失了Specific
的构造函数。我真的只想要在__mro__
中插入一个没有副作用的类。可能的?
答案 0 :(得分:1)
您正在抛弃当前的类层次结构,因为您正在从另一个基类构建一个新类。如果Special
是混合,将添加到当前类层次结构中。继承Special
和cls
:
class Meta(type):
def __call__(cls, *args, special=False, **kwargs):
if special:
cls = cls.__class__(cls.__name__ + Special.__name__, (Special, cls), {})
return super(Meta, cls).__call__(*args, **kwargs)
然后输出变为:
>>> c = Specific(special=True)
construct Base
construct Concrete
construct Specific
construct Special
>>> print(c.__class__.__mro__)
(<class '__main__.SpecificSpecial'>, <class '__main__.Special'>, <class '__main__.Specific'>, <class '__main__.Concrete'>, <class '__main__.Base'>, <class 'object'>)
这会将Special
放在层次结构中的其他类之前。如果您需要Special
来Specific
和Concrete
(但Base
之前),请交换基类订单:
cls = cls.__class__(cls.__name__ + Special.__name__, (cls, Special), {})
请注意,每次创建实例时都会创建一个新类 。您可能希望缓存这些类,以至少避免增加类对象。