为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

Cats萌萌 2022-11-01 17:16:28
我正在尝试使用多重继承向我拥有的现有类之一添加一些功能。问题是这个新类和我当前的基类在它们的构造函数中有不同的参数。即新类有 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'
查看完整描述

3 回答

?
波斯汪

TA贡献1811条经验 获得超4个赞

这段代码对我有用!!!


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)


查看完整回答
反对 回复 2022-11-01
?
RISEBY

TA贡献1856条经验 获得超5个赞

根据 MRO,调用转到Hafter D,因此,如果您需要 send 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)。另一种方法是,如果您交换E,H继承顺序,MRO 就可以解决,您就不需要这样做,或者单独使用E.__init__()and H.__init__()。在这种情况下,MRO 会再次发生变化,如果需要,公共类将被调用两次。

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



查看完整回答
反对 回复 2022-11-01
?
达令说

TA贡献1821条经验 获得超6个赞

很难知道您要处理的业务案例是什么,以及是什么驱动了这种特定的继承形式。话虽这么说,你得到了例外,因为类'I'首先调用'E'的init,然后才调用'H'。


解决该问题的最简单方法是将 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())

这解决了这个问题。


查看完整回答
反对 回复 2022-11-01
  • 3 回答
  • 0 关注
  • 148 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信