在python中,有很多关于类继承的场景和知识点。今天重点关注一个场景:有一个父类A,定义了某个问题中的通用属性和方法(也就是后面需要用到所有的子类),这些属性和方法需要在子类B中继承,并且同时如何添加自己独特的属性和方法?在子类中,继承和初始化父类的属性有两种方式:显式调用父类的初始化函数,对属性进行初始化;通过super()初始化父类的属性;对于方法1,代码:classA:def__init__(self,a,b):self.a=aself.b=bdeffunc(self):returnself.a+self.bclassB(A):def__init__(self,x1,x2,x3,x4):A.__init__(self,a=x1,b=x2)#注意必须传入self,相当于传入B的实例self.c=x3self.d=x4self.m=A.func(self)#也必须传入selfself.n=self.func()>>>ins=B(1,2,10,20)>>>print(ins.a,ins.b,ins.c,ins.d)121020>>>print(ins.m,ins.n)33>>>print(ins.func())3对于方法二,代码:classA:def__init__(self,a,b):self.a=aself.b=bdeffunc(self):returnself.a+self.bclassB(A):def__init__(自我,x1,x2,x3,x4):超级()。__init__(a=x1,b=x2)#初始化父类参数,注意不需要selfself.c=x3self.d=x4self.m=super().func()#super()也可以调用父类方法self.n=self.func()#也可以直接调用使用父类方法>>>ins=B(1,2,10,20)>>>print(ins.a,ins.b,ins.c,ins.d)121020>>>print(ins.m,ins.n)33>>>print(ins.func())3对于方法1,初始化显示调用,多重继承时可能会出现重复调用,如:classA:def__init__(self,a,b):self.a=aself.b=bprint('AAAAA')deffunc(self):returnself.a+self.bclassB(A):def__init__(self,x1,x2,x3,x4):A.__init__(self,a=x1,b=x2)self.c=x3self.d=x4print('BBBBB')classC(A):def__init__(self,m,n,q):A.__init__(self,m,n)self.q=qprint('CCCCC')类D(B,C):def__init__(self,a,b,c,d,e,f):B.__init__(self,a,b,c,d)C.__init__(self,a,b,e)self.f=fprint('DDDDDD')>>>ins=D(1,2,3),4,5,6)AAAAAABBBBBAAAAACCCCCDDDDDD可以看到A被调用了两次,因为D继承了B和C,初始化B的时候会先初始化A,再初始化B;初始化C时,也会先初始化A,再初始化C;因此A被初始化了两次。还有一个问题就是,虽然使用super()可以避免重复调用的问题,但是当父类有参数需要初始化的时候就很麻烦了:classA:def__init__(self):print('AAAAA')deffunc(self):返回self.a+self.bclassB(A):def__init__(self):super().__init__()print('BBBBB')classC(A):def__init__(self):super().__init__()print('CCCCC')classD(B,C):def__init__(self):super().__init__()print('DDDDDD')>>>ins=D()AAAAACCCCCBBBBBDDDDDD#可见,确实可以避免重复调用的问题。但是,如果父类有参数,那么这时候问题就很大了,比如:classA:def__init__(self,a,b):self.a=aself.b=bprint('AAAAA')deffunc(self):返回self.a+self.b类B(A):def__init__(self,x1,x2,x3,x4):super().__init__(x1,x2)self.c=x3self.d=x4print('BBBBB')C类(A):def__init__(self,m,n,q):super().__init__(m,n)self.q=qprint('CCCCC')classD(B,C):def__init__(self,a,b,c,d,e,f):super().__init__(a,b,c,d)##在这种情况下,因为它是根据对MRO规则来说,所有的父类都被初始化了,所以不管这里怎么传参数,都有可能报错。因为不同父类的入参是不一样的。根据后面看的MRO顺序,调用顺序是D-B-C-A,所以这里初始化的时候IDE会提示输入4个参数,因为B是先调用的,B的初始化需要4个参数。self.f=fprint('DDDDDD')>>>ins=D(1,2,3,4,5,6)TypeError:__init__()missing1requiredpositionalargument:'q'>>>print(D.__mro__)#查看D的父类调用MRO的顺序(
