一、继承
定义一个类时,需要使用另外一个类的方法或属性,就可以通过继承实现
object是Python的顶级类,创建类是会自动继承,就拥有object中的方法
-
定义格式
# 类的定义 # 旧式类定义 一般在定义单个类时使用 class 类名: name = None def func(self): pass # 新式类定义 一般在继承时使用 class 类名(指定需要继承的类): name = None def func(self): pass
# 新式类定义 class A(): name = '张三' def func(self): # pass 不做处理 pass # 旧式类 class B: age = 20 def fucn(self): pass print(A.name) print(B.age)
1-1 单继承
一次继承一个类
(1)Father类有一个性别属性,默认为男,同时,Father跑步速度快;
(2)如果Son类也想要拥有这些属性和方法,该怎么做呢?
(3)执行程序,观察程序效果。
# 单继承 只继承一个类 class Father: gender = '男' def run(self): print('跑步很快') # 子类继承父类获取父类中属性和方法 class Son(Father): # 定义子类的属性和方法 age = 20 def play(self): print('玩游戏') # 创建子类对象 s = Son() # 使用子类对象操作父类的属性和方法以及自己的属性和方法 print(s.gender) print(s.age) s.run() s.play()
(1)从前,有个摊煎饼的老师傅[Master],在煎饼果子界摸爬滚打多年,研发了一套精湛的摊煎饼(flapjack)技术;
(2)渐渐地,老师傅老了,就想着把这套技术传授给他唯一的最得意的徒弟[Apprentice];
(3)试着通过初始化、无参、定义方法与单继承来模拟程序。
# 单继承的使用 class Master: name = '师父' def flapjack(self): print('摊鸡蛋煎饼') class Apprentice(Master): # 子类继承后可以不定义属性和方法,直接使用父类的方法 pass a = Apprentice() # 子类使用父类方法 a.flapjack()
1-2 多继承
继承多个类
(1)徒弟是个爱学习的好孩子,想学习更多的摊煎饼技术;
(2)于是,在百度搜索到黑马程序员学校[School],报班来培训学习如何摊煎饼;
(3)使用多继承形式模拟程序。
# 单继承的使用 class Master: name = '师父' def flapjack(self): print('摊鸡蛋煎饼') class School: name = '学校' def flapjack(self): print('摊肉肠煎饼') class Apprentice(Master,School): # 子类继承后可以不定义属性和方法,直接使用父类的方法 pass a = Apprentice() # 子类使用父类方法 a.flapjack() # 查看子类的继承父类顺序 print(Apprentice.__mro__)
(1)可以发现老师傅[Master]、培训学校[School]都有摊煎饼方法;
(2)在徒弟对象中调用摊煎饼方法,会执行哪个父类的方法呢?
调用第一个父类的方法,print(Apprentice.
__mro__
) # 查看类的继承执行顺序(3)思考:当给父类培训学校[School]新增编程方法后,子类能调用方法吗?
多继承时,父类方法都能被继承,但是如果有相同方法名,则在执行方法时,会按照print(Apprentice.
__mro__
)显示的顺序查找方法执行如果想要能后执行所有父类方法,则需要将函数名字进行修改,避免函数名冲突
# 单继承的使用 class Master: name = '师父' def master_flapjack(self): print('摊鸡蛋煎饼') class School: name = '学校' def school_flapjack(self): print('摊肉肠煎饼') class Apprentice(School,Master): # 子类继承后可以不定义属性和方法,直接使用父类的方法 pass a = Apprentice() # 子类使用父类方法 a.master_flapjack() a.school_flapjack() # 查看子类的继承父类顺序 print(Apprentice.__mro__)
1-3 方法重写
子类中定义了和父类相同的方法,就是对父类方法的重写,在执行方法时,使用的是子类的逻辑代码
(1)徒弟非常认真学习,终于掌握了老师傅的技术;
(2)接着,自己潜心钻研出类独门配方的全新摊煎饼技术;
(3)使用方法重写对摊煎饼方法进行处理。
当对父类方法重写后,执行时只会执行子类的的方法逻辑,不会再执行父类方法中的逻辑
# 重写父类方法 子类继承父类后定义了一个和父类相同名字的方法 # 单继承的使用 class Master: name = '师父' def flapjack(self): print('摊鸡蛋煎饼') class Apprentice(Master): # 子类中定义了自己方法,和父类方法名一样 # 子类相当于重写了父类的方法,在执行时按照子类的逻辑执行 def flapjack(self): print('摊手抓饼') a = Apprentice() a.flapjack()
子类重写父类方法,在调用时执行的子类的逻辑,还想调用父类方方法,需要借助super()方法实现
(1)徒弟在培训学校学习努力,不仅掌握了黑马摊煎饼配方、还创办了自己煎饼果子的品牌;[配方、品牌]
(2)配合着一起摊煎饼,做出了更加美味的煎饼果子;
(3)使用调用父类方法在
__init__()
和摊煎饼方法中处理。
# 重写父类方法 子类继承父类后定义了一个和父类相同名字的方法 # 单继承的使用 class Master: name = '师父' def flapjack(self): print('摊鸡蛋煎饼') class Apprentice(Master): # 子类中定义了自己方法,和父类方法名一样 # 子类相当于重写了父类的方法,在执行时按照子类的逻辑执行 def flapjack(self): # 在子类中调用父类相同的方法 使用super() # 通过super可以获取父类对象 print(super().name) print('摊手抓饼') super().flapjack() a = Apprentice() a.flapjack()
1-4 多层继承
(1)N年后,当初的徒弟也老了;
(2)因此,徒弟想要把"有自己品牌,也有黑马配方的煎饼果子"的所有技术传授给自己的小徒弟;
(3)请试着使用多层继承的方式完成案例。
# 多层继承 # 重写父类方法 子类继承父类后定义了一个和父类相同名字的方法 # 单继承的使用 class Master: name = '师父' def flapjack(self): print('摊鸡蛋煎饼') class Apprentice(Master): name = '徒弟' def flapjack(self): print('摊手抓饼') super().flapjack() class LittleApprentice(Apprentice): name = '小弟' def flapjack(self): print('蒸包子') super().flapjack() # 创建对象 la = LittleApprentice() la.flapjack() print(LittleApprentice.__mro__)
# 多层继承 # 重写父类方法 子类继承父类后定义了一个和父类相同名字的方法 # 单继承的使用 class Master: name = '师父' def flapjack(self): print('摊鸡蛋煎饼') class School: name = '学校' def school_flapjack(self): print('摊肉肠煎饼') class Apprentice(Master,School): name = '徒弟' def flapjack(self): print('摊手抓饼') super().flapjack() class LittleApprentice(Apprentice): name = '小弟' def flapjack(self): print('蒸包子') super().flapjack() # 创建对象 la = LittleApprentice() la.flapjack() la.school_flapjack() print(LittleApprentice.__mro__)
二、多态
多态指的是一类事物的多中形态
相同的方法,产生不同的执行结果
运算符 + * 的多态
int + int 加法计算
str + str 字符串拼接
list + list 列表的数据合并
在python中可以使用类实现一个多态效果
在python中使用重写的方式实现多态
(1)定义两个类:老师、车;
(2)定义老师类的属性:姓名,定义老师类的方法:开车、停车;
(3)定义车类的属性:类型,定义车类的方法:开启、停止;
(4)联系:老师开车,执行程序,观察效果;
# 多态 class Teacher: def __init__(self,name): self.name = name def run(self): print(f'{self.name}老师开车') def stop(self): print(f'{self.name}老师停车') class Car: def __init__(self,type): self.type = type def start(self): print(f'{self.type}启动') def close(self): print(f'{self.type}熄火') t = Teacher('张三') c = Car('小汽车') c.start() t.run() c.close() t.stop()
使用继承方式,调整执行的方法
# 多态 class Teacher: def __init__(self,name): self.name = name def run(self): print(f'{self.name}老师开车') def stop(self): print(f'{self.name}老师停车') class Car(Teacher): def __init__(self,type,name): super().__init__(name) self.type = type def start(self): print(f'{self.type}启动') super().run() def close(self): print(f'{self.type}熄火') super().stop() c = Car('小汽车','张三') c.start() c.close()
(5)思考:老师有可能开小轿车、骑自行车、坐地铁等,该怎么改进程序呢?
使用子类的重写功能实现多态
多态实现的流程
1-定义一个父类,在父类中定义需要执行的业务方法,具体方法的逻辑不用实现,直接pass,由继承的子类实现
2-定义多个功能的子类继承父类,在子类中对父类方法重写,实现自己子类的逻辑
3-封装一个统一的函数处理方法,让开发人员调用该方法
# 多态 class Teacher: def __init__(self,name): self.name = name def run(self): pass def stop(self): pass class Car(Teacher): def __init__(self,type,name): super().__init__(name) self.type = type def run(self): # 在多态实现时,子类继承父类并对父类方法进行重写 print(f'{self.type}启动') print(f'{self.name}老师开车') def stop(self): print(f'{self.type}熄火') print(f'{self.name}老师停车') class Metro(Teacher): def __init__(self,type,name): super().__init__(name) self.type = type def run(self): # 在多态实现时,子类继承父类并对父类方法进行重写 print(f'{self.type}启动') print(f'{self.name}老师乘坐地铁') def stop(self): print(f'{self.type}到站') print(f'{self.name}老师下车') # 单独封装一个行为函数 # 该函数就是对外提供一个函数接口,其他开发人员使用,就调用函数 def action(obj): # obj接收一个对象 obj.run() obj.stop() c = Car('越野车','张三') action(c) m = Metro('地铁1号线','李四') action(m)