python - 调用 super().__init__ 时,如何判断超级初始化是否是 python3 中的 object.__init__?
问题描述
给定一个任意的类继承,我如何找出 if super().__init__ == object.__init__
?
描述 + 示例
我有这个我不允许触摸的代码,它定义了类 A、B、C、CombinedCba、CombinedAc,每个类都有这个奇怪__init__
的约束来验证实例属性。当在所有基类中进行 init 调用时,我们会收到错误:
TypeError: object.__init__() takes exactly one argument (the instance to initialize)
所以为了防止这个错误,当它是对象初始化时,我们应该停止调用超级初始化。我能够编辑 super_init 函数。如何检测超级初始化何时为初始化?如果我知道我无法进行下一次超级初始化调用并消除错误。
# code that I can edit
def super_init(self, super_instance, *args, **kwargs):
# checking super_instance.__init__ == object.__init__ OR super_instance.__init__ is object.__init__ doesn't work
# pseudo-code
if super_instance.__init__ is not object.__init__:
super_instance.__init__(*args, **kwargs)
# auto generated code is from here on down
class A:
def __init__(self, *args, **kwargs):
self.a = kwargs['a']
assert self.a == 'a'
super_init(self, super(), *args, **kwargs)
class B:
def __init__(self, *args, **kwargs):
self.b = kwargs['b']
self.some_num = kwargs['some_num']
assert self.some_num <= 30
super_init(self, super(), *args, **kwargs)
class C:
def __init__(self, *args, **kwargs):
self.some_num = kwargs['some_num']
assert self.some_num >= 10
super_init(self, super(), *args, **kwargs)
class CombinedCba(C, B, A):
pass
combo_cba = CombinedCba(a='a', b='b', some_num=25)
class CombinedAc(A, C):
pass
combo_ac = CombinedAc(a='a', some_num=15)
解决方案
首先,定义A
、B
和正确C
使用super
:
class A:
def __init__(self, a, **kwargs):
super().__init__(**kwargs)
assert a == 'a'
self.a = a
class B:
def __init__(self, b, some_num, *args, **kwargs):
super().__init__(**kwargs)
self.b = b
self.some_num = some_num
assert self.some_num <= 30
class C:
def __init__(self, some_num, **kwargs):
super().__init__(**kwargs)
self.some_num = some_num
assert self.some_num >= 10
特别是,请注意B
和C
声明“所有权” some_num
,而不必担心另一个类可能会使用它。
接下来,定义一个混合类,它只确保some_num
用于设置some_num
属性。
class SomeNumAdaptor:
def __init__(self, some_num, **kwargs):
self.some_num = some_num
super().__init__(**kwargs)
第三,定义包装器B
并C
获取some_num
from的值,self
以便将其添加回关键字参数(已SomeNumAdaptor
剥离):
class CWrapper(C):
def __init__(self, **kwargs):
super().__init__(some_num=self.some_num, **kwargs)
class BWrapper(B):
def __init__(self, **kwargs):
super().__init__(some_num=self.some_num, **kwargs)
这意味着B
和C
都将“重置” 的值self.num
。
B
(如果您还可以修改并C
使其成为some_num
可选并检查是否存在,则不需要包装器self.some_num
。)
SomeNumAdaptor
最后,根据包装类定义您的组合类。SomeNumAdaptor
您必须从first继承,以确保BWrapper
和CWrapper
findsome_num
作为属性,而不管它们的相对顺序如何。
class CombinedAbc(SomeNumAdaptor, A, BWrapper, CWrapper):
pass
class CombinedCba(SomeNumAdaptor, CWrapper, BWrapper, A):
pass
combo_cba = CombinedCba(a='a', b='b', some_num=25)
combo_abc = CombinedAbc(a='a', b='b', some_num=15)
以上所有假设既不B
也不C
将其some_num
参数的修改值存储到属性中。如果是这样,您将需要更复杂的包装器来处理它,可能不仅仅是将接收到的值传递给__init__
. B
请注意,这可能表明同时从两者继承的一个更基本的问题C
。
推荐阅读
- android - 从多个用户更新 Firestore 文档映射
- rust - 将异步函数传递给另一块代码(不能满足编译器)
- c - BMP 转换段错误 - alloc 或其他
- java - 我有一个旧的声音类,我想将它从使用 applet.AudioClip 更改为现代的东西,这样我就可以改变音量。我该怎么做?
- javascript - 如何在 d3.js v5 上的饼图中放置图例
- python - 读取文件中的“IndexError:单个位置索引器越界”
- excel - VBA获取像素颜色
- javascript - ContextAPI 在页面重新加载和在新选项卡中打开时丢失状态
- php - 包含数据库数据的数组
- c++ - 为什么这个函数多次输出一个单词而不是一个?