继承
- 单继承和多继承
- 单继承:每个类只能继承一个类
- 多继承:每个类允许继承多个类
>>> class A():
pass
>>> class B(A):
pass
>>> class C(B,A):
pass
>>> print(A.__mro__)
>>> print(B.__mro__)
输出:
(<class '__main__.A'>, <class 'object'>)
(<class '__main__.B'>, <class '__main__.A'>, <class 'object'>)
# 子类可以直接拥有父类的属性和方法,私有属性和方法除外
>>> class Fish():
def __init__(self, name):
self.name = name
def swim(self):
print('{} can swimming......'.format(self.name))
>>> class Bird():
def __init__(self, name):
self.name = name
def fly(self):
print('{} can fly......'.format(self.name))
>>> class Person():
def __init__(self, name):
self.name = name
def work(self):
print("Working......")
# 单继承的例子
>>> class Student(Person):
def __init__(self, name):
self.name = name
# 多继承
>>> class SuperMan(Person, Bird, Fish):
def __init__(self, name):
self.name = name
>>> s = SuperMan('小明')
>>> s.fly()
>>> s.swim()
输出:
小明 can fly......
小明 can swimming......
- 单继承和多继承的优缺点
- 单继承:
- 传承有序逻辑清晰语法简单隐患少
- 功能不能无限扩展,只能在当前唯一的继承链中扩展
- 多继承:
- 菱形继承/钻石继承
- 多个子类继承自同一个父类,这些子类又被同一个类继承,于是继承关系图形成一个菱形图谱
- MRO
- 关于多继承的MRO
- MRO就是多继承中,用于保存继承顺序的一个列表
- python本身采用C3算法来做多继承的菱形继承进行计算的结果
- MRO列表的计算原则:
- 子类永远在父类前面
- 如果多个父类,则根据继承语法中括号内类的书写顺序存放
- 如果多个类继承了同一个父类,孙子类中只会选取继承语法括号中第一个父类的父类
# 菱形问题
>>> class A():
pass
>>> class B(A):
pass
>>> class C(A):
pass
>>> class D(B,C):
pass
- 构造函数
- 在对象进行实例化的时候,系统自动调用的一个函数叫构造函数,通常此函数用来实例化对象进行初始化,顾名构造函数,在python中叫魔术函数、魔法函数。
- 构造函数一定要有,如果没有,则自动向上查找,按照MRO顺序,直到找到为止
# 构造函数例子
>>> class Person():
# 对Person类进行实例化的时候
# 姓名要确定
# 年龄得确定
# 地址肯定有
def __init__(self):
self.name = "NoName"
self.age = 18
self.address = 'earth'
print("I am a Student")
# 实例化一个人
>>> p = Person()
>>> print(p.__dict__)
输出:
I am a Student
{'name': 'NoName', 'age': 18, 'address': 'earth'}
---------------------------------------------------------------------------------------------------
# 构造函数的调用顺序 -1
# 如果子类没有写构造函数,则自动向上查找,直到找到为止
>>> class A():
def __init__(self):
print("A")
>>> class B(A):
def __init__(self):
print("B")
>>> class C(B):
pass
# 此时,首先查找C的构造函数
# 如果没有,则向上按照MRO顺序查找父类的构造函数,直到找到为止
>>> c = C() # C类没有构造函数 找C的父类B 找到了 然后停止 不再向上找
---------------------------------------------------------------------------------------------------
# 构造函数的调用顺序 -2
>>> class A():
def __init__(self):
print("A")
>>> class B(A):
def __init__(self, name):
print("B")
print(name)
>>> class C(B):
pass
# 此时,首先查找C的构造函数
# 如果没有,则向上按照MRO顺序查找父类的构造函数,直到找到为止
# 此时,会出现参数结构不对应错误
# c = C() # 此处 C类没有构造函数 向上找到C的父类B的构造函数 但B类构造函数需要两个参数
>>> cc = C('哈哈')
输出:
B
哈哈
---------------------------------------------------------------------------------------------------
# 构造函数的调用顺序 -3
>>> class A():
def __init__(self):
print("A")
>>> class B(A):
def __init__(self, name):
print("B")
print(name)
>>> class C(B):
# c中想扩展B的构造函数,
# 即调用B的构造函数后再添加一些功能
# 有两种方法实现
'''
# 第一种是通过父类名调用
def __init__(self, name):
# 首先调用父类的构造函数
B.__init__(self, name)
#其次,再增加自己的功能
print("这是C中附加的功能")
'''
# 第二种,使用super调用
def __init__(self, name):
# 首先调用父类构造函数
super(C, self).__init__(name)
# 其次,再增加自己的功能
print("这是C中附加的功能")
>>> c = C("我是C")
输出:
B
我是C
这是C中附加的功能
多态
- 多态就是同一个对象在不同情况下有不同的状态出现
- 多态不是语法,是一种设计思想
- 多态性:一种调用方式,不同的执行效果
- 多态:同一事物的多种形态,动物分为人类、狗类、猪类
多态和多态性
- Mixin设计模式
- 我们使用多继承语法来是吸纳Mixin
- 使用Mixin实现多继承的时候要非常小心
- 首先他必须表示某一单一功能,而不是某个物品
- 职责必须单一,如果有多个功能,则写多个Mixin
- Mixin不能依赖于子类的实现
- 子类即使没有继承这个Mixin类,也能照样工作,只是缺少了某个功能
- 优点
- 使用Minxin可以在不对类进行任何修改的情况下,扩充功能
- 可以方便的组织和维护不同功能组件的划分
- 可以根据需要任意调整功能类的组合
- 可以避免创建很多新的类,导致类的继承混乱
# Mixin案例
>>> class Person():
name = '小明'
age =18
def eat(self):
print("EAT....")
def drink(self):
print("Drink....")
def sleep(self):
print("SLEEP....")
>>> class Teacher(Person):
def work(self):
print("WORK....")
>>> class Teacher(Person):
def work(self):
print("WORK....")
>>> class Student(Person):
def study(self):
print("STUDY....")
>>> class Tutor(Teacher, Student):
pass
>>> t = Tutor()
>>> print(Tutor.__mro__)
>>> print(t.__dict__)
>>> print(Tutor.__dict__)
>>> print("*" * 20)
>>> class TeacherMixin():
def work(self):
print("Work")
>>> class StudentMixin():
def study(self):
print("Study")
>>> class TutorM(Person, TeacherMixin, StudentMixin):
pass
>>> tt = TutorM()
>>> print(TutorM.__mro__)
>>> print(tt.__dict__)
>>> print(TutorM.__dict__)
输出:
(<class '__main__.Tutor'>, <class '__main__.Teacher'>, <class '__main__.Student'>, <class '__main__.Person'>, <class 'object'>)
{}
{'__module__': '__main__', '__doc__': None}
********************
(<class '__main__.TutorM'>, <class '__main__.Person'>, <class '__main__.TeacherMixin'>, <class '__main__.StudentMixin'>, <class 'object'>)
{}
{'__module__': '__main__', '__doc__': None}