【发布时间】:2020-12-19 11:26:30
【问题描述】:
据我了解,如果所有类都使用“新样式”,那么会发生这种情况:
class A(object):
def __init__(self):
print("Entering A")
super().__init__()
print("Leaving A")
class B(object):
def __init__(self):
print("Entering B")
super().__init__()
print("Leaving B")
class C(A, B):
def __init__(self):
print("Entering C")
super().__init__()
print("Leaving C")
c = C()
Entering C
Entering A
Entering B
Leaving B
Leaving A
Leaving C
在了解 super 使用原始对象 (c) 的 MRO 之后,Entering/Leaving 为何如此是有道理的。但是如果我需要将一些特定的参数传递给A和B,而且C中接收参数的顺序与A和B不相似:
class A(object):
def __init__(self, x1, x2):
print(f"Entering A [x1={x1}, x2={x2}]")
super().__init__()
print("Leaving A")
class B(object):
def __init__(self, y1, y2):
print(f"Entering B [y1={y1}, y2={y2}]")
super().__init__()
print("Leaving B")
class C(A, B):
def __init__(self, x1, y1, x2, y2):
print(f"Entering C [x1={x1}, y1={y1}, x2={x2}, y2={y2}]")
super().__init__()
print("Leaving C")
c = C('x1', 'y1', 'x2', 'y2')
我可以考虑整天路过kwargs,但我觉得可能有更好的方法。
另外,如果B 是库的一部分,因此我们无法更改它并且它使用位置参数,而不是kwargs,该怎么办?在这种情况下,我该怎么办,因为我认为手动弄乱 MRO 不是一个好主意,但同时B 的构造函数不会采用kwargs?
解决上述问题的正确方法是什么?
【问题讨论】:
-
我很困惑,你想在不知道构造函数前面有哪个父级和什么签名的情况下调用父级的构造函数?如果您需要灵活性,您可以使用
kwargs执行此操作并获得所需的位,但“正确”的方法是调用A.__init__(self, x1, x2)和B.__init__(self, y1, y2)。没有魔法,没有歧义。 -
@OndrejK.but 那不是“旧风格”吗?我了解您如何使用该样式,但这意味着“新样式”应该能够完成“旧样式”所能做的所有事情,并在此基础上提供一些额外的好处(在这种情况下,分解代码更健壮)。
-
对于你所描述的,这不是“旧式”的问题,而是关于设计/意图的explicit。
-
@OndrejK。如果它不能执行与“旧样式”相同的任务,您能否解释一下为什么要引入这种“新样式”?
标签: python oop inheritance multiple-inheritance