Python 3.x Python-为多个父类调用_init
编辑:我在Python 3上 我有一个类Python 3.x Python-为多个父类调用_init,python-3.x,Python 3.x,编辑:我在Python 3上 我有一个类X,它扩展了Y和Z: class X(Y, Z): def __init__(self): # Call Y's __init__ # Call Z's __init pass 我需要在Y和Z上调用\uuuuuu init\uuuuuu,从X上的\uuuuuu调用。最好的方法是什么 这完全取决于Y和Z是否设计为与多重继承协同工作。如果是,那么您应该能够只使用super: class X(Y, Z): def __i
X
,它扩展了Y
和Z
:
class X(Y, Z):
def __init__(self):
# Call Y's __init__
# Call Z's __init
pass
我需要在
Y
和Z
上调用\uuuuuu init\uuuuuu
,从X
上的\uuuuuu
调用。最好的方法是什么 这完全取决于Y
和Z
是否设计为与多重继承协同工作。如果是,那么您应该能够只使用super
:
class X(Y, Z):
def __init__(self):
super().__init__()
当我说Y
和Z
需要设计为与多重继承协同工作时,我的意思是它们还必须在\uuuuuu init\uuuu
方法中调用super:
class Y:
def __init__(self):
print('Y.__init__')
super().__init__()
class Z:
def __init__(self):
print('Z.__init__')
super().__init__()
它们还应该有一些处理不同参数的策略,因为类(尤其是构造函数)在接受哪些关键字参数方面经常不同。在这一点上,有必要阅读并理解一些关于超级计算机的常见习语和陷阱
如果您不知道Y
和Z
是否设计用于合作多重继承,那么最安全的方法是假设它们不是
如果这些类不是为协同多重继承而设计的,那么您需要开始轻举妄动(您处于危险境地)。您可以分别调用每个\uuuuu init\uuuu
:
class X(Y, Z):
def __init__(self):
Y.__init__(self)
Z.__init__(self)
但实际上,最好不要使用多重继承,而是选择不同的范式(例如组合)。一般来说,没有其他方法可以直接调用Y.\uuuu init\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuo(self)
。这是确保两个构造函数至少调用一次的唯一方法
但是,在某些奇怪的情况下(或正常情况,取决于您如何看待),这可能会导致非常不直观的结果,其中多次调用基本构造函数:
class Y:
def __init__(self):
print('Y')
super().__init__()
class Z:
def __init__(self):
print('Z')
super().__init__()
class X(Y, Z):
def __init__(self):
print('X')
Y.__init__(self)
Z.__init__(self)
X()
导致
X
Y
Z
Z
因此在这种情况下,super()。X
中的
初始化
(而不是两个。\uu初始化
调用)看起来很自然,可以正常工作。但是,如果Y
和Z
不调用super()。\uuuu init\uuuuu()
,它将失败。在这种情况下,您将只调用一个构造函数
所以一般来说,如果不知道基类的实现,就无法正确地解决问题
YARtAMI=避免多重继承的另一个原因是这是Python 2还是Python 3?我使用Python 3。这是另一个原因,为什么多重继承是不好的,那么您如何在这种不好的实践中询问最佳实践呢?好的,我删除了关于最佳实践的部分。现在你的建议是什么?在我的例子中,父母是-
threading.Thread
和logging.Handler
-我如何检查他们是否被设计为在多重继承中协同工作?据我所知,不是。@masnun你需要问自己的问题是:为什么你想从他们两个继承?你在混合不相关的概念。使用一个类并将它们都作为字段(或其他干净模式)会更干净。@mgilson我猜Handler
也不使用super
。我可以在它自己的中看到它调用filter.\uuuu init\uuuu(self)
。感谢您的解释。让我们假设Y
也有一个基类(Q
),并且Y
调用super()。\uuu init\uu()
,以确保它(隐式)调用Q.\uu init\uu()
。根据方法解析顺序,Y
的super()。如果Z.\uuuuu init\uuuuu
也super
s,那么您将调用Z.\uuuuu init\uuuuuu
两次(在此处调用一次,以后显式调用一次)。如果Z.\uuuuu init\uuuu
没有super
,那么您可能会完全跳过Q.\uuuuu init\uuuu
。感谢您的详细解释。在我的例子中,没有一个父类有任何共同的祖先。我已经更新了答案。是否有任何解释可以解释为什么Y中的第一个调用super()。\uuu init\uu()
会触发Z.\uu init\uu()???我知道Y和Z继承自对象
,所以我不明白为什么第一个“Z”会打印在屏幕上