python3中具有不同签名的多重继承 [英] Multiple inheritance in python3 with different signatures

查看:180
本文介绍了python3中具有不同签名的多重继承的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有三个课程: A B C

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

C inherits from A and B (in this order). The constructor signatures of A and B are different. How can I call the __init__ methods of both parent classes?

我在代码中的努力:

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

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

I found this resource which explains mutiple inheritance with different set of arguments, but they suggest to use *args and **kwargs to use for all argument. I consider this very ugly, since I cannot see from the constructor call in the child class what kind of parameters I pass to the parent classes.

推荐答案

使用 super(baseclass,...)除非你知道自己在做什么。 super()的第一个参数告诉它在查找下一个要使用的方法时跳过的类。例如。 super(A,...)将查看MRO,找到 A ,然后开始寻找<$ c 下一个基类, A 本身$ c> __ init __ 。对于 C ,MRO是(C,A,B,对象),所以 super (A,self).__ init __ 将找到 B .__ init __

Do not use super(baseclass, ...) unless you know what you are doing. The first argument to super() tells it what class to skip when looking for the next method to use. E.g. super(A, ...) will look at the MRO, find A, then start looking for __init__ on the next baseclass, not A itself. For C, the MRO is (C, A, B, object), so super(A, self).__init__ will find B.__init__.

对于这些在某些情况下,您不想使用协作继承,而是直接引用 A .__ init __ B .__ init __ super()只应在您调用的方法具有相同签名或者使用 *吞下不支持的参数时使用args ** vargs 。在这种情况下,只需要一个 super(C,self).__ init __()调用,并且MRO命令中的下一个类将负责处理呼叫。

For these cases, you don't want to use cooperative inheritance but directly reference A.__init__ and B.__init__ instead. super() should only be used if the methods you are calling have the same signature or will swallow unsupported arguments with *args and **vargs. In that case just the one super(C, self).__init__() call would be needed and the next class in the MRO order would take care of chaining on the call.

换句话说:当你使用 super()时,你无法知道接下来会是什么类MRO,以便该类更好地支持您传递给它的参数。如果不是这样,请使用 super()

Putting it differently: when you use super(), you can not know what class will be next in the MRO, so that class better support the arguments you pass to it. If that isn't the case, do not use 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()

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

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

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

这篇关于python3中具有不同签名的多重继承的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆