浅析python继承与多重继承
记住以下几点:
直接子类化内置类型(如dict,list或str)容易出错,因为内置类型的方法通常会忽略用户覆盖的方法,不要子类化内置类型,用户自定义的类应该继承collections模块。
def__setitem__(self,key,value): super().__setitem__(key,[value]*2)#错误案例 classAnswerDict(dict): def__getitem__(self,item):#错误案例 return42 importcollections classDoppelDict2(collections.UserDict):#正确案例 def__setitem__(self,key,value): super().__setitem__(key,[value]*2) classAnswerDict2(collections.UserDict):#正确案例 def__getitem__(self,item): return42
多重继承有关的另一个问题就是:如果同级别的超类定义了同名属性.Python如何确定使用哪个?
classDoppelDict(dict): def__setitem__(self,key,value): super().__setitem__(key,[value]*2) classAnswerDict(dict): def__getitem__(self,item): return42 importcollections classDoppelDict2(collections.UserDict): def__setitem__(self,key,value): super().__setitem__(key,[value]*2) classAnswerDict2(collections.UserDict): def__getitem__(self,item): return42 classA: defping(self): print('Ping:',self) classB(A): defpong(self): print('pong:',self) classC(A): defpong(self): print('PONG:',self) classD(B,C): defping(self): super().ping() print('post-ping:',self) defpingpong(self): self.ping() super().ping() self.pong() super().pong() C.pong(self) if__name__=='__main__': d=D() print(d.pong())#输出来源于B print(C.pong(d))#输出来源于C超类的方法都可以直接调用,此时要把实例作为显示参数传入.
python能区别调用的是哪个方法,通过方法解析顺序
>>>D.mro()
[
若想把方法调用委托给超类,推荐的方式是使用内置的super()函数.
以下是对于d.pingpong()方法的解读
>>>self.ping()
Ping:<__main__.Dobjectat0x000002213877F2B0>post-ping:<__main__.Dobjectat0x000002213877F2B0>第一个调用的是self.ping(),运行的是是D类的ping,方法.
第二个调用的的是super().ping(),跳过D类的ping方法,找到A类的ping方法.Ping:<__main__.Dobjectat0x000002213877F2B0>
第三个调用的是self.pong()方法,根据__mro__,找到B类实现的pong方法.pong:<__main__.Dobjectat0x000002213877F2B0>
第四个调用时super().pong(),也是根据__mro__,找到B类实现的pong方法.pong:<__main__.Dobjectat0x000002213877F2B0>
第五个调用的是C.pong(self),忽略了__mro__,找到的是C类实现的pong方法.PONG:<__main__.Dobjectat0x000002213877F2B0>