python3中具有不同签名的多重继承

时间:2014-11-14 10:13:51

标签: python inheritance python-3.x multiple-inheritance

我有三个班级:ABC

C继承自AB(按此顺序)。 AB的构造函数签名不同。如何调用两个父类的__init__方法?

我在代码中的努力:

class A(object):
    def __init__(self, a, b):
        super(A, self).__init__()
        print('Init {} with arguments {}'.format(self.__class__.__name__, (a, b)))

class B(object):
    def __init__(self, q):
        super(B, self).__init__()
        print('Init {} with arguments {}'.format(self.__class__.__name__, (q)))

class C(A, B):
    def __init__(self):
        super(A, self).__init__(1, 2)
        super(B, self).__init__(3)

c = C()

产生错误:

Traceback (most recent call last):
  File "test.py", line 16, in <module>
    c = C()
  File "test.py", line 13, in __init__
    super(A, self).__init__(1, 2)
TypeError: __init__() takes 2 positional arguments but 3 were given

我发现this resource解释了使用不同参数集的多重继承,但他们建议使用*args**kwargs来用于所有参数。我认为这非常难看,因为我无法从子类中的构造函数调用中看到我传递给父类的哪种参数。

1 个答案:

答案 0 :(得分:67)

使用super(baseclass, ...),除非您知道自己在做什么。 super()的第一个参数告诉它在查找下一个要使用的方法时跳过的类。例如。 super(A, ...)会查看MRO,找到A,然后开始在下一个基类上查找__init__ {{1本身。对于A,MRO为C,因此(C, A, B, object)会找到super(A, self).__init__

对于这些情况,您不希望使用合作继承,而是直接引用B.__init__A.__init__。只有在您调用的方法具有相同签名或将使用B.__init__super()吞下不受支持的参数时,才应使用*args。在这种情况下,只需要进行一次**vargs调用,并且MRO命令中的下一个类将负责处理呼叫。

换句话说:当你使用super(C, self).__init__()时,你无法知道MRO中接下来会是什么类,所以这个类更好地支持你传递给它的参数。如果不是这种情况,请使用super()

直接调用基本super()方法:

__init__

使用合作class A(object): def __init__(self, a, b): print('Init {} with arguments {}'.format(self.__class__.__name__, (a, b))) class B(object): def __init__(self, q): print('Init {} with arguments {}'.format(self.__class__.__name__, (q))) class C(A, B): def __init__(self): # Unbound functions, so pass in self explicitly A.__init__(self, 1, 2) B.__init__(self, 3)

super()