在Python中使用多类继承动态创建类型时调用Super

qij5mzcb  于 2023-05-02  发布在  Python
关注(0)|答案(1)|浏览(130)

如何通过协作继承动态创建从多个基类继承的type?我尝试了几个选项,每个选项都有自己的问题。我当前的代码是这样工作的:

cls_map = {"SomeClass" : SomeClass, "OtherClass" : OtherClass}

    def get_type(classes: list[str]):

        def constructor(self, *args, **kwargs):
            pass

        types: list[type] = [cls_map[c] for c in classes]
   
        return type("MutableEntity", tuple(types), {
            "__init__": constructor
        })
        
    # Get type, instantiate object
    dynamic_cls: type = get_type(['SomeClass', 'OtherClass'])
    dynamic_instance = dynamic_cls(...)

当我执行时

assert isinstance(dynamic_instance, SomeClass)

它返回True(这太棒了!).
我遇到的问题是我不知道如何让constructor正确地调用super().__init__(*args, **kwargs)
我试过:

def constructor(self, *args, **kwargs):
            pass

但出现以下错误:
E TypeError: super(type, obj): obj must be an instance or subtype of type
我的理论是,这是因为参数self由于某种原因是None。有什么建议可以解决这个问题吗?我的子类设计为使用协作继承,所以能够调用super()很重要。
完整代码:

class SomeClass:
    def __init__(self, *args, **kwargs):
        super(*args, **kwargs)
        self.some_class = True

class OtherClass:
    def __init__(self, *args, **kwargs):
        super(*args, **kwargs)
        self.other_class = True

cls_map = {"SomeClass": SomeClass, "OtherClass": OtherClass}

def get_type(classes: list[str]):
    def constructor(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

    types: list[type] = [cls_map[c] for c in classes]

    return type("MutableEntity", tuple(types), {
        "__init__": constructor
    })

# Get type, instantiate object
dynamic_cls: type = get_type(['SomeClass', 'OtherClass'])
dynamic_instance = dynamic_cls()

assert hasattr(dynamic_instance, 'some_class')
assert hasattr(dynamic_instance, 'other_class')
xoshrz7s

xoshrz7s1#

您需要类似于:

def constructor(self, *args, **kwargs):
    super(klass, self).__init__(*args, **kwargs)

klass = type(
    "MutableEntity", 
     tuple(types), 
     {"__init__": constructor}
)

return klass

零参数形式只在类定义语句内部工作(通过编译器魔法)。
注意,你的基类也需要调用super,否则这将不起作用(不写适配器类)

相关问题