You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python Mixins:调用super()时如何处理*args与**kwargs?

如何让Mixin支持任意组合与继承顺序?

下面的示例尝试使用Mixin模式,但运行时会触发类型错误:

class AMixin():
    def __init__(self, **kwargs):
        print("AMixin")
        self.a = 'a' + str(kwargs.get('a', ''))
        super().__init__(**kwargs)
        
class BMixin():
    def __init__(self, **kwargs):
        print("BMixin")        
        self.b = 'b' + str(kwargs.get('b', ''))
        super().__init__(**kwargs)
                
class ABMixin(AMixin, BMixin):
    def __init__(self, **kwargs):
        print("ABMixin")
        super().__init__(**kwargs)
    
class A(AMixin):
    def __init__(self, **kwargs):
        super().__init__(**kwargs)
    
class B(BMixin):
    def __init__(self, **kwargs):
        super().__init__(**kwargs)
    
class AB(ABMixin):
    def __init__(self, **kwargs):
        print("AB")
        super().__init__(**kwargs)
    
AB(a='a', b='b')

错误信息

Cell In [4], line 9, in BMixin.__init__(self, *args, **kwargs)
      8 def __init__(self, *args, **kwargs):
----> 9     super().__init__(*args, **kwargs)
     10     print("BMixin")
     11     self.b = 'b' + str(kwargs.get('b', ''))

TypeError: object.__init__() takes exactly one argument 
           (the instance to initialize)

错误原因

Python的多继承方法解析顺序(MRO)中,当Mixin通过super()调用父类构造方法时,继承链的最终节点是object类。而object.__init__仅接受self一个参数,传入额外的**kwargs就会触发类型错误。

解决方案

方案1:添加空基类EndMixin

创建一个空的EndMixin作为所有Mixin的基类,它的__init__方法接收**kwargs但不做任何逻辑处理,让继承链的最终节点指向它而非object:

class EndMixin:
    def __init__(self, **kwargs):
        pass  # 仅接收参数,无实际逻辑
        
class AMixin(EndMixin):
    def __init__(self, **kwargs):
        print("AMixin")
        self.a = 'a' + str(kwargs.get('a', ''))
        super().__init__(**kwargs)  # 传递参数到下一个节点
        
class BMixin(EndMixin):
    def __init__(self, **kwargs):
        print("BMixin")        
        self.b = 'b' + str(kwargs.get('b', ''))
        super().__init__(**kwargs)

这样无论Mixin以何种顺序组合,super()调用最终都会落到EndMixin.__init__,不会触发参数错误。

方案2:动态判断父类__init__参数

如果不想额外添加基类,可以在每个Mixin的__init__中,先判断父类的构造方法是否接受关键字参数,再决定如何调用:

import inspect

class AMixin():
    def __init__(self, **kwargs):
        print("AMixin")
        self.a = 'a' + str(kwargs.get('a', ''))
        # 获取父类构造方法的签名
        parent_init = super().__init__
        sig = inspect.signature(parent_init)
        # 检查是否支持关键字参数
        supports_kwargs = any(param.kind == param.VAR_KEYWORD for param in sig.parameters.values())
        if supports_kwargs:
            super().__init__(**kwargs)
        else:
            super().__init__()

class BMixin():
    def __init__(self, **kwargs):
        print("BMixin")        
        self.b = 'b' + str(kwargs.get('b', ''))
        parent_init = super().__init__
        sig = inspect.signature(parent_init)
        supports_kwargs = any(param.kind == param.VAR_KEYWORD for param in sig.parameters.values())
        if supports_kwargs:
            super().__init__(**kwargs)
        else:
            super().__init__()

这种方式无需额外基类,但代码相对繁琐,适合无法修改Mixin继承结构的场景。


内容的提问来源于stack exchange,提问作者nowox

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.13 20:05:37