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)) # <type 'instance'>
# 新式类
b = B()
print(b.__class__)
print(type(b))
多继承
- OCP原则:多用“继承”、少修改
- 继承的用途:在子类上实现对基类的增强、实现多态
- 多态
- 在面向对象中,父类、子类通过继承联系在一起,如果可以通过一套方法,就可以实现不同表现,就是多态。
- 一个类继承自多个类就是多继承,它将具有多个类的特征。
多继承弊端
- 多继承很好的模拟了世界,因为事物很少是单一继承,但是舍弃简单,必然引入复杂性,带来了冲突。
- 多继承的实现会导致编译器设计的复杂度增加,所以有些高级编程语言舍弃了类的多继承。
- C++支持多继承;Java舍弃了多继承。
- Java中,一个类可以实现多个接口,一个接口也可以继承多个接口。Java的接口很纯粹,只是方法的声明,继承者必须实现这些方法,就具有了这些能力,就能干什么。
- 多继承可能会带来二义性,实现多继承的语言,要解决二义性,深度优先或者广度优先。
Python多继承实现
- 左图是多继承(菱形继承),右图是单一继承
- 多继承带来路径选择问题
- Python使用MRO(method resolution order方法解析顺序)解决基类搜索顺序问题。
- 历史原因,MRO有三个搜索算法:
- 经典算法,按照定义从左到右,深度优先策略。2.2版本之前
左图的MRO是MyClass,D,B,A,C,A - 新式类算法,是经典算法的升级,深度优先,重复的只保留最后一个。2.2版本
左图的MRO是MyClass,D,B,C,A,object - 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())
# [<class '__main__.PrintableWord'>, <class '__main__.PrintableMixin'>, <class '__main__.Word'>, <class '__main__.Document'>, <class 'object'>]
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())
# [<class '__main__.SuperprintablePdf'>, <class '__main__.SuperPrintableMixin'>,\
# <class '__main__.PrintableMixin'>, <class '__main__.Pdf'>, \
# <class '__main__.Document'>, <class 'object'>]
spp = SuperprintablePdf('super print pdf')
spp.print()
# --------------------
# super print pdf Mixin
# --------------------