[英]When calling super().__init__ how can I tell if the super init is object.__init__ in python3?
给定任意 class inheritance 我如何找出super().__init__ == object.__init__
?
我有这个我不允许触摸的代码,它定义了类 A、B、C、CombinedCba、CombinedAc,每个 class 都有这个奇怪的__init__
约束,它验证实例属性。 当在所有基类中进行 init 调用时,我们会收到错误:
TypeError: object.__init__() takes exactly one argument (the instance to initialize)
所以为了防止这个错误,当它是 object init 时,我们应该停止调用 super init。 我可以编辑 super_init function。 如何检测超级初始化何时为初始化? 如果我知道我无法进行下一次超级初始化调用并消除错误。
# 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)
我能够完成这项工作的唯一方法是构建一个新的临时 class 包含剩余的超类,然后检查该 class 的__init__
方法。
def super_init(self, super_instance, *args, **kwargs):
classes_in_order = self.__class__.__mro__
for i, cls in enumerate(classes_in_order):
if cls == super_instance.__thisclass__:
remainder_cls = type('_unused', classes_in_order[i+1:], {})
super_init_is_object_init = remainder_cls.__init__ == object.__init__
if not super_init_is_object_init:
super_instance.__init__(*args, **kwargs)
这些尝试没有奏效:
super().__init__ == object.__init__
不起作用super().__init__ is object.__init__
没有工作super(super().__thisclass__, self)
与object.__init__
没有用inspect.signature
反省 function 签名不起作用 首先,定义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
,而不必担心另一个 class 可能会使用它。
接下来,定义一个混合 class,它只确保使用some_num
设置some_num
属性。
class SomeNumAdaptor:
def __init__(self, some_num, **kwargs):
self.some_num = some_num
super().__init__(**kwargs)
第三,为B
和C
定义包装器,它们从self
获取some_num
的值,以便将其作为关键字参数添加回来( 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
继承,以确保BWrapper
和CWrapper
找到some_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
继承存在更基本的问题。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.