如何让Python多继承的所有父类接收相同的kwargs参数?
实现多继承下所有父类获取同一组关键字参数
问题原因
你示例中的Second拿到空kwargs,是因为First的__init__调用super时没有传递*args和**kwargs。即使修正这个问题,默认情况下如果某个父类从kwargs中弹出键,后续父类也会丢失该键。要让所有父类都能获取完整的原始kwargs(除非显式弹出),可以用以下几种方案:
方案一:手动调用每个父类的__init__
绕过super链,直接在子类中调用每个父类的初始化方法,传递完整参数。这种方法简单直接,适合父类之间无依赖的场景。
class First(object): def __init__(self, *args, **kwargs): print('First', kwargs) class Second(object): def __init__(self, *args, **kwargs): print('Second', kwargs) class Third(First, Second): def __init__(self, *args, **kwargs): # 手动调用所有父类的初始化方法,传递完整参数 First.__init__(self, *args, **kwargs) Second.__init__(self, *args, **kwargs) print('Third', kwargs)
测试输出:
In [1]: tc = Third(key='value', someother='nothing') First {'key': 'value', 'someother': 'nothing'} Second {'key': 'value', 'someother': 'nothing'} Third {'key': 'value', 'someother': 'nothing'}
注意:该方法会跳过Python的MRO机制,如果父类依赖super链的后续初始化逻辑,可能引发问题。
方案二:预存原始kwargs到实例属性
在子类中先把完整的kwargs保存到实例,父类优先从实例获取原始参数,同时保留super链的兼容性。
class First(object): def __init__(self, *args, **kwargs): # 优先使用实例预存的原始kwargs,无则用传入的参数 current_kwargs = getattr(self, '_original_kwargs', kwargs) print('First', current_kwargs) # 若需要弹出键,操作副本避免影响其他父类 # local_kwargs = current_kwargs.copy() # target_key = local_kwargs.pop('key', None) super().__init__(*args, **kwargs) class Second(object): def __init__(self, *args, **kwargs): current_kwargs = getattr(self, '_original_kwargs', kwargs) print('Second', current_kwargs) super().__init__(*args, **kwargs) class Third(First, Second): def __init__(self, *args, **kwargs): # 预存原始kwargs到实例 self._original_kwargs = kwargs.copy() super().__init__(*args, **kwargs) print('Third', kwargs)
测试输出:
In [2]: tc = Third(key='value', someother='nothing') Second {'key': 'value', 'someother': 'nothing'} First {'key': 'value', 'someother': 'nothing'} Third {'key': 'value', 'someother': 'nothing'}
方案三:在super链中传递kwargs副本
每个父类调用super时传递kwargs的副本,确保后续父类拿到的是完整参数,不受当前父类的修改影响。
class First(object): def __init__(self, *args, **kwargs): print('First', kwargs) # 传递kwargs副本给下一个父类 super().__init__(*args, kwargs.copy()) class Second(object): def __init__(self, *args, **kwargs): print('Second', kwargs) super().__init__(*args, kwargs.copy()) class Third(First, Second): def __init__(self, *args, **kwargs): super().__init__(*args, kwargs.copy()) print('Third', kwargs)
测试输出:
In [3]: tc = Third(key='value', someother='nothing') Second {'key': 'value', 'someother': 'nothing'} First {'key': 'value', 'someother': 'nothing'} Third {'key': 'value', 'someother': 'nothing'}
如果需要在父类中弹出特定键,操作副本即可:
class First(object): def __init__(self, *args, **kwargs): local_kwargs = kwargs.copy() key = local_kwargs.pop('key', None) print('First 获取到key:', key, '剩余参数:', local_kwargs) # 仍传递原始副本给后续父类 super().__init__(*args, kwargs.copy())
内容的提问来源于stack exchange,提问作者TM5
相关产品推荐
相关产品推荐

