Paranoid丶 发表于 2021-1-29 10:51

【Python求助】关于带参数的钻石继承问题

本帖最后由 Paranoid丶 于 2021-1-29 13:47 编辑

这几天在自学Python,但学到类的继承的时候自己尝试出现了问题,使用的python版本为3.6.6

自己在百度上找了很久,没找到可以参照的例子,满屏的CSDN基本都是同一篇文章。。、

### 问题描述

钻石继承带参数的时候,运行到最后一个类出现错误:`__init__() missing 1 required positional argument: 'c'`



### 程序代码

```python
class A:
    def __init__(self,a):
      self.a=a
      print(self.a)
      
class B(A):
    def __init__(self,a,b):
      super().__init__(a)
      self.b=b
      print(self.b)
      
class C(A):
    def __init__(self,a,c):
      super().__init__(a)
      self.c=c
      print(self.c)
      
class D(B,C):
   def __init__(self,a,b,c,d):
      B.__init__(self,a,b)
      C.__init__(self,a,c)
      self.d=d
      print(self.d)

def main():
    A(1)
    B(2,3)
    C(4,5)
    D(6,7,8,9)
   
   
if __name__=='__main__':
    main()
```

ufo0033 发表于 2021-1-29 13:20

本帖最后由 ufo0033 于 2021-1-29 13:41 编辑

python的钻石继承 实际上 是被拉成了线性。从d来看,分别继承b和c 那么b的super().__init__(a)实际上是在给c 初始化。这里开始参数不对了,
class A:
    def __init__(self, a, *args, **kwargs):
      print('进入A')
      self.a = a
      print("A message:", self.a)
      print('离开A')


class B(A):
    def __init__(self, b, *args, **kwargs):
      print('进入B')
      super(B, self).__init__(*args, **kwargs)
      self.b = b
      print("B message:", self.b)
      print('离开B')


class C(A):
    def __init__(self, c, *args, **kwargs):
      print('进入C')
      super(C, self).__init__(*args, **kwargs)
      self.c = c
      print("C message:",self.c)
      print('离开C')


class D(B, C):
    def __init__(self, d, *args, **kwargs):
      print('进入D')
      super(D, self).__init__(*args, **kwargs)
      self.d = d
      print("D message:",self.d)
      print('离开D')


def main():
    # A(1)
    # B(2, 3)
    # C(4, 5)
    D(6, 7, 8, 9)


if __name__ == '__main__':
    main()

这样设计的目的是为了防止 A被多次初始化

gongsui 发表于 2021-1-29 11:07

看描述应该是说参数3个但是你给了4个

jiangpeng59 发表于 2021-1-29 11:09

D的父类都没有接受3个参数的 __init__方法,肯定会报错啊

Paranoid丶 发表于 2021-1-29 11:09

gongsui 发表于 2021-1-29 11:07
看描述应该是说参数3个但是你给了4个

但是我在super给的参数是三个:a,b,c

Paranoid丶 发表于 2021-1-29 11:17

jiangpeng59 发表于 2021-1-29 11:09
D的父类都没有接受3个参数的 __init__方法,肯定会报错啊

{:301_1009:}所以没有办法接受多个父类的参数吗

boryou 发表于 2021-1-29 12:39

试了下好像class B 里的那个super会调用A的__init__然后还会调用C的__init__,所以报错,原理不知道
另外,为啥用B.__init__(self) 这种方式啊

古月不傲 发表于 2021-1-29 13:03

class A:
    def __init__(self,a):
      self.a=a
      print(self.a)

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

class C(A):
    def __init__(self,a,c):
      A.__init__(self, a)
      self.c=c
      print(self.c)

class D(B,C):
   def __init__(self,a,b,c,d):
      B.__init__(self, a,b)
      C.__init__(self, a,c)
      self.d=d
      print(self.d)

def main():
    A(6)
    B(6,7)
    C(6,7)
    D(6,7,8,9)

if __name__=='__main__':
    main()


这样没问题,至于为什么我也不知道,python我不熟悉,不过构造顺序到是和c++的规则一样

Paranoid丶 发表于 2021-1-29 13:43

ufo0033 发表于 2021-1-29 13:20
python的钻石继承 实际上 是被拉成了线性。从d来看,分别继承b和c 那么b的super().__init__(a)实际上 ...

学到了,感谢

古月不傲 发表于 2021-1-29 13:49

ufo0033 发表于 2021-1-29 13:20
python的钻石继承 实际上 是被拉成了线性。从d来看,分别继承b和c 那么b的super().__init__(a)实际上 ...

这种设计牛逼阿,免去了一次构造和析构,不知道C++种有没有这种解决方案
页: [1] 2
查看完整版本: 【Python求助】关于带参数的钻石继承问题