TypeError:具有不同参数的python多重继承

Bob*_*ano 7 python multiple-inheritance

我正在尝试使用多重继承向我拥有的现有类之一添加一些功能。问题是这个新类和我当前的基类在它们的构造函数中有不同的参数。即新类有 1 个额外的参数。经过一番谷歌搜索,我明白我可以将 **kwargs 添加到当前基类(少一个参数的基类)。例子:

class A(object):
    def __init__(self, a):
        print('__init__', locals())


class B(A):
    def __init__(self, a, b):
        super(B, self).__init__(a)
        print('__init__', locals())


class C(B):
    def __init__(self, a, b):
        super(C, self).__init__(a, b)
        print('__init__', locals())


class D(C):
    def __init__(self, a, b):
        super(D, self).__init__(a, b)
        print('__init__', locals())


class E(D):
    def __init__(self, a, b, *args, **kwargs):
        super(E, self).__init__(a, b)
        print('__init__', locals())


class F(C):
    def __init__(self, a, b):
        super(F, self).__init__(a, b)
        print('__init__', locals())


class G(F):
    def __init__(self, a, b, c):
        super(G, self).__init__(a, b)
        print('__init__', locals())


class H(G):
    def __init__(self, a, b, c):
        super(H, self).__init__(a, b, c)
        print('__init__', locals())


class I(E, H):
    def __init__(self, a, b, c):
        super(I, self).__init__(a, b, c=c)
        print('__init__', locals())


for c in I.__mro__:
        print(c)


I(0, 1, 2)
Run Code Online (Sandbox Code Playgroud)

但我收到此错误:

<class '__main__.I'>
<class '__main__.E'>
<class '__main__.D'>
<class '__main__.H'>
<class '__main__.G'>
<class '__main__.F'>
<class '__main__.C'>
<class '__main__.B'>
<class '__main__.A'>
<class 'object'>
Traceback (most recent call last):
  File "/tmp/c.py", line 58, in <module>
    I(0,1,2)
  File "/tmp/c.py", line 50, in __init__
    super(I, self).__init__(a, b, c=c)
  File "/tmp/c.py", line 26, in __init__
    super(E, self).__init__(a, b)
  File "/tmp/c.py", line 20, in __init__
    super(D, self).__init__(a, b)
TypeError: __init__() missing 1 required positional argument: 'c'
Run Code Online (Sandbox Code Playgroud)

Saj*_*hil 3

根据 MRO,调用将转到Hafter D,因此,如果您需要发送c,类D将需要接受它并发送 3 个参数,即 H将被调用D。例如:

class A(object):
    def __init__(self, a):
        print('a')
        print('__init__', locals())

class B(A):
    def __init__(self, a, b):
        print('b')
        super(B, self).__init__(a)

        print('__init__', locals())

class C(B):
    def __init__(self, a, b):
        print('c')
        super(C, self).__init__(a, b)

        print('__init__', locals())

class D(C):
    def __init__(self, a, b, *args, **kwargs):
        print('d', args, kwargs)
        super(D, self).__init__(a, b, args, kwargs)

        print('__init__', locals())

class E(D):
    def __init__(self, a, b, *args, **kwargs):
        print('e', args, kwargs)
        super(E, self).__init__(a, b)

        print('__init__', locals())

class F(C):
    def __init__(self, a, b):
        print('f')
        super(F, self).__init__(a, b)

        print('__init__', locals())

class G(F):
    def __init__(self, a, b, c):
        print('g')
        super(G, self).__init__(a, b)

        print('__init__', locals())

class H(G):
    def __init__(self, a, b, c, *args, **kwargs):
        print('h')        
        super(H, self).__init__(a, b, c)

        print('__init__', locals())

class I(E,H):
    def __init__(self, a, b, c):
        print('i')
        super(I,self).__init__(a, b, c)
        #E.__init__(self,a, b)
        #H.__init__(self,a, b, c)

        print('__init__', locals())

for c in I.__mro__:
        print(c)

I(0, 1, 2)
Run Code Online (Sandbox Code Playgroud)

这段代码有效,(我已更改c为 arg 而不是**kwarg)。另一种方法是,如果你交换E,H继承顺序,MRO 就会起作用,你就不需要这样做,或者单独使用E.__init__()和。H.__init__()在这种情况下,MRO再次发生变化,如果需要的话,公共类将被调用两次。

对于 MRO,我找到了这个答案和Guido Van Rossum 的这篇博客文章(也在另一个答案中链接),这可能会帮助您深入了解 python 中的 MRO 算法。