Python--多继承(Mixin类)

Python不同版本的类

  • Python2.2之前类是没有共同的祖先的,之后,引入object类,它是所有类的共同祖先类object。
  • Python2中为了兼容,分为古典类(旧式类)和新式类。
  • Python3中全部都是新式类。
  • 新式类都是继承自object的,新式类可以使用super。
# 以下代码在Python2.x中运行
# 古典类(旧式类)
class A: pass

# 新式类
class B(object): pass

print(dir(A))
print(dir(B))
print(A.__bases__)
print(B.__bases__)

# 古典类
a = A()
print(a.__class__)
print(type(a)) # 

# 新式类
b = B()
print(b.__class__)
print(type(b))

多继承

  • OCP原则:多用“继承”、少修改
  • 继承的用途:在子类上实现对基类的增强、实现多态
  • 多态
  • 在面向对象中,父类、子类通过继承联系在一起,如果可以通过一套方法,就可以实现不同表现,就是多态。
  • 一个类继承自多个类就是多继承,它将具有多个类的特征。

多继承弊端

  • 多继承很好的模拟了世界,因为事物很少是单一继承,但是舍弃简单,必然引入复杂性,带来了冲突。
  • 多继承的实现会导致编译器设计的复杂度增加,所以有些高级编程语言舍弃了类的多继承。
  • C++支持多继承;Java舍弃了多继承。
  • Java中,一个类可以实现多个接口,一个接口也可以继承多个接口。Java的接口很纯粹,只是方法的声明,继承者必须实现这些方法,就具有了这些能力,就能干什么。
  • 多继承可能会带来二义性,实现多继承的语言,要解决二义性,深度优先或者广度优先。

Python多继承实现

Python--多继承(Mixin类)_第1张图片

  • 左图是多继承(菱形继承),右图是单一继承
  • 多继承带来路径选择问题
  • Python使用MRO(method resolution order方法解析顺序)解决基类搜索顺序问题。
  • 历史原因,MRO有三个搜索算法:
  1. 经典算法,按照定义从左到右,深度优先策略。2.2版本之前
    左图的MRO是MyClass,D,B,A,C,A
  2. 新式类算法,是经典算法的升级,深度优先,重复的只保留最后一个。2.2版本
    左图的MRO是MyClass,D,B,C,A,object
  3. C3算法,在类被创建出来的时候,就计算出一个MRO有序列表。2.3之后,Python3唯一支持的算法
    左图中的MRO是MyClass,D,B,C,A,object的列表

C3算法解决多继承的二义性
C3算法,解决了继承的单调性,它阻止创建之前版本产生二义性的代码。求得的MRO本质是为了线性化,且确定了顺序。
单调性:假设有A、B、C三个类,C的mro是[C, A, B],那么C的子类的mro中,A、B的顺序一致就是单调的。

Mixin类

  • Mixin本质上就是多继承实现的
  • Mixin体现的是一种组合的设计模式
  • 在面向对象的设计中,一个复杂的类,往往需要很多功能,而这些功能有来自不同的类提供,这就需要很多的类组合在一起
  • 从设计模式的角度来说,多组合,少继承

Mixin类的使用原则

  • Mixin类中不应该显式的出现__init__初始化方法
  • Mixin类通常不能独立工作,因为它是准备混入别的类中的部分功能实现
  • Mixin类的祖先类也应是Mixin类
  • 使用时,Mixin类通常在继承列表的第一个位置
  • 父类只做方法的定义
  • 抽象类,抽象方法
  • 其他语言抽象类不可实例化
  • 抽象类一般不实例化,作为基类用
class Document: # 第三方库,不允许修改
	def __init__(self, content):
		self.content = content

class Word(Document): pass # 第三方库,不允许修改
class Pdf(Document): pass # 第三方库,不允许修改

class PrintableMixin:
	def print(self):
		print(self.content, 'Mixin') 

class PrintableWord(PrintableMixin, Word): pass
print(PrintableWord.__dict__) # {'__module__': '__main__', '__doc__': None}
print(PrintableWord.mro())
# [, , , , ]

pw = PrintableWord('test string')
pw.print() # test string Mixin

class SuperPrintableMixin(PrintableMixin):
    def print(self):
        print('-' * 20) # 打印增强
        super().print()
        print('-' * 20) # 打印增强

# PrintableMixin类的继承
class SuperprintablePdf(SuperPrintableMixin, Pdf): pass

print(SuperprintablePdf.__dict__) # {'__module__': '__main__', '__doc__': None}
print(SuperprintablePdf.mro())
# [, ,\
# , , \
# , ]

spp = SuperprintablePdf('super print pdf')
spp.print()
# --------------------
# super print pdf Mixin
# --------------------

你可能感兴趣的:(Python--多继承(Mixin类))