python类的多继承关系_Python-面向对象之多继承

多继承

一个类继承自多个类就是多继承,它将具有多个类的属性型和方法。

多继承的弊端

多继承 很好的模拟了世界,因为事物是单一继承,但是舍弃简单,必然引起复杂性,带来了冲突。

如同一个孩子继承了父母双方的特性,那么到底是眼睛更像父亲还是母亲呢?孩子究竟像谁多一点呢?

多继承的实现会导致设计的复杂度增加,所以有些高级编程语言直接舍去了多继承。

C++支持多继承,Java舍弃了多继承。

多继承可能带来二义性,例如,猫和狗都是继承自动物类,现在如果一个类多继承了猫和狗类,猫和狗都有shout方法,子类究竟继承谁的shout呢?

解决方案:

实现多继承的语言,要解决二义性,深度优先和广度优先。

Python多继承实现

classClassName(基类1,基类2[,......])

语句块

1978004-20200520163435648-150119737.png

左图是多继承(菱形继承),右图是单一继承。

多继承带来路径选择问题,究竟继承哪个父类的特征呢?

Python使用了MRO(method resolution order 方法解析顺序)解决基类的搜索顺序问题。

1978004-20200520163733280-1294414650.png

多继承的缺点

当类很多且继承复杂的情况下,继承路径太多,很难说清楚什么样的继承路径,Python语法是允许多继承,但Python代码是解释器执行,只有执行到的时候才知道发现错误,团队协作开发,如果引入多继承,那代码很可能失控。

不管编程语言是否支持多继承,都应该避免多继承,Python的面向对象,我们看到了太灵活了,太开放了,所以需要团队守规矩。

MIXIN

类有一下继承关系

1978004-20200520164203714-550010987.png

文档Document类是其他所有文档类的抽象基类,Word,PDF类是Document的子类。

需求:为Document子类提供打印功能

使用单继承实现

classDocument:def __init__(self,content):

self.content=contentclassWord(Document):pass

classPdf(Document):pass

classPrintWord(Word):def __init__(self,content):

self.content=contentdef print(self):print(self.content)

pw= PrintWord("test print word")

pw.print()print(PrintWord.__dict__.items())print(PrintWord.mro())#输出

test printword

dict_items([('__module__', '__main__'), ('__init__', ), ('print', ), ('__doc__', None)])

[, , ,]

上诉方法看似不错,如果需要还要提供其他的能力,如何继承?

例如,如果该类用于网络传输,还应该具备序列化的能力,在类上就应该实现序列化。

可序列化还可能分为使用pickle、json、messagepack等。

这个时候发现,为了增加一种能力,就需要增加一次继承,类可能太多了,继承的方式不是很好。

可提供的功能太多,A类需要某几种功能,B类需要某几种功能,他们需要的是多个功能的自由组合,继承实现很繁琐。

使用装饰器实现

用一个装饰器增强一个类,把功能给类加上去,哪个类需要就给哪个类添加,装饰它。

defprintable(cls):def_print(self):print(self.content,'装饰器')

cls.print =_printreturnclsclassDocument:def __init__(self,content):

self.content=content

@printableclassWord(Document):pass@printableclassPdf(Document):pass

classPrintWord(Word):pass

classPrintPdf(Pdf):passpw= PrintWord("test print word")

pw.print()print(PrintWord.__dict__.items())print(PrintWord.mro())

pd= PrintPdf("print Pdf")

pd.print()print(PrintPdf.__dict__.items())print(PrintWord.mro())

testprintword 装饰器

dict_items([('__module__', '__main__'), ('__doc__', None)])

[, , , ]printPdf 装饰器

dict_items([('__module__', '__main__'), ('__doc__', None)])

[, , , ]

优点:

简单方便,在需要的地方动态增加,直接使用装饰器。

可以为类灵活的增加功能。

Mixin

classDocument:def __init__(self,content):

self.content=contentclass Word(Document): pass

class Pdf(Document): pass

classPrintableMixin:def print(self):print(self.content,'Mixin')class PrintableWord(PrintableMixin,Word): pass

print(PrintableWord.mro())print(PrintableWord.__dict__)

pw= PrintableWord("test word print")

pw.print()defPrintable(cls):def_print(self):print(self.content,'装饰器')

cls.print =_printreturncls

@Printableclass PrintPdf(Pdf): passpd= PrintPdf("test pdf print")

pd.print()print(PrintPdf.mro())print(PrintPdf.__dict__)#输出

[, , , , ]

{'__module__': '__main__', '__doc__': None}

test wordprintMixin

test pdfprint装饰器

[, , , ]

{'__module__': '__main__', '__doc__': None, 'print': ._print at 0x0000012A825300D0>}

Mixin就是其他类混合进来,同时带来了类的属性和方法。

这里看来Mixin类和装饰器效果一样,也没有什么特别的地方,但是Mixin是类,就可以继承。

classDocument:def __init__(self,content):

self.content=contentclass Word(Document): pass

class Pdf(Document): pass

classPrintableMixin:def print(self):print(self.content,'Mixin')class PrintableWord(PrintableMixin,Word): pass

print(PrintableWord.mro())print(PrintableWord.__dict__)

pw= PrintableWord("test word print")

pw.print()classSuperPrintableMixin(PrintableMixin):def print(self):print("~" * 30)

super().print()print("~" * 30)classSuperPrintablePdf(SuperPrintableMixin,Pdf):passsupper= SuperPrintablePdf("supper print pdf")

supper.print()#输出

[, , , , ]

{'__module__': '__main__', '__doc__': None}

test wordprintMixin~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~supperprintpdf Mixin~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Mixin类

Mixin本质上是多继承实现的,Mixin体现是一种组合的设计模型。

在面向对象的设计中,一个复杂的类,往往需要很多功能,而这些功能有来自不同的类提供,这就需要很多类组合在一起,

从设计的模式来讲,多组合,少继承。

Mixin类的使用原则

Mixin类中不应该显式的出现__init__初始化方法

Mixin类通常补鞥呢独立工作,因为它是准备混入别的类中的部分功能实现

Mixin类的祖先类也应该是Mixin类

使用Mixin类通常在继承列表中的第一个位置

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值