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



我正在尝试使用多重继承为我现有的一个类添加一些功能。问题是这个新类和我当前的基类的构造函数中有不同的参数。也就是说,新类有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)

但我得到了这个错误:

<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'

这段代码适用于我!!!

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

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

class C(B):
def __init__(self, a, b):
B.__init__(self,a, b)
print("C class")

class D(C):
def __init__(self, a,b):
C.__init__(self,a, b)
print("D class")

class F(C):
def __init__(self, a,b):
#C.__init__(self,a, b)
print("F class")

class G(F):
def __init__(self, a, b, c):
F.__init__(self,a, b)
print("G class")
class E(D):
def __init__(self, a, b):
D.__init__(self,a, b)
print("E class")

class H(G):
def __init__(self, a,b,c):
G.__init__(self,a, b, c)
print("H class")

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

print(I.__mro__)
I(1,2,3)

根据MRO,调用在D之后转到H,因此,如果需要发送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)

该代码有效,(我已将c更改为arg,而不是**kwarg(。另一种方法是,如果您交换EH继承顺序,MRO就可以解决,您不需要这样做,或者分别使用E.__init__()H.__init__()。在这种情况下,MRO将再次更改,如果需要,公共类将被调用两次。

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

很难知道您试图处理的业务案例是什么,以及是什么驱动了这种特定形式的继承。话虽如此,您会得到异常,因为类"I"首先调用"E"的init,然后才调用"H"的init。

解决这个问题的最简单方法是将I的基类的顺序切换到在您的情况下似乎更自然的顺序:

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

这就解决了问题。

最新更新