引入
1.什么是继承
- 继承是一种新建类的方式, 新建的类称为子类, 被继承的类称为父类
- 继承的特性 : 子类会遗传父类的属性
- 继承是类与类之间的关系
2.为什么使用继承 (作用)
- 使用继承可以减少代码的冗余
- 示例:
不使用继承时编写多个类
class Animal:
def run(self):
print("奔跑")
def eat(self):
print("吃东西")
class Duck:
def run(self):
print("奔跑")
def eat(self):
print("吃东西")
def speak(self):
print("嘎嘎嘎")
class Pig:
def run(self):
print("奔跑")
def eat(self):
print("吃东西")
def speak(self):
print("咕咕咕")
class Person:
def run(self):
print("奔跑")
def eat(self):
print("吃东西")
def speak(self):
print("呵呵呵")
使用继承编写多个类
class Animal:
def run(self):
print("奔跑")
def eat(self):
print("吃东西")
class Duck(Animal):
def speak(self):
print("嘎嘎嘎")
class Pig(Animal):
def speak(self):
print("咕咕咕")
class Person(Animal):
def speak(self):
print("呵呵呵")
#可以明显感觉到代码量减少
一.类(对象)的继承
- Python中一切皆对象, 所以类也是对象
- Python中支持一个类同时继承多个父类 (多继承)
class Animal:
def run(self):
print("跑起来")
class Work:
def doing(self):
print("敲代码")
class Person(Animal,Work): # 可以继承很多个类,用","隔开
def eat(self):
print("吃东西")
__bases__
: 查看对象继承的类
print(Person.__bases__) # (<class '__main__.Animal'>, <class '__main__.Work'>) 两个
二.属性查找顺序
1.多继承属性查找顺序
-
多继承存在属性重复问题, 多个父类中存在着相同的属性, 那么对象该选择哪个属性使用呢?
-
按照右边顺序查找 : 对象自己----->类----->父类 (多个父类,从左到右的先后顺序来找)
class Shawn:
def Am(self):
print("i am from Shawn")
class Pai:
def Am(self):
print("i am from Pai")
class Da:
def Am(self):
print("i am from Da")
class Xing(Pai,Shawn,Da): # 继承了三个父类,查找顺序:从左到右
pass
start = Xing()
start.Am() # i am from Pai (找到的是最左边的)
2.属性嵌套查找顺序 (多层继承)
- 对象的属性 (attribute) : 我们一般是指对象的属性和方法
- 多层继承关系的属性查找顺序, 永远是从最下层开始找,调用自己
self.[属性]
- 以下示例的数查找顺序 : 对象自己----->对象的类----->父类----->父类.....
ps : Ctrl + 鼠标右键 快速跳转到属性 / 方法位置, 有时并不准确
class Bar1(object):
def Foo1(self):
print("i am Bar1_Foo1")
def Foo2(self):
print("i am Bar1_Foo2")
self.Foo1() ###
class Bar2(Bar1):
def Foo1(self):
print("i am Bar2_Foo1")
obj = Bar2()
obj.Foo2()
'''输出
i am Bar1_Foo2 (对象自己没有到父类去找)
i am Bar2_Foo1 (执行到"self.Foo1()"后又返回来从最开始找)
'''
三.新式类与经典类
1.新式类
- 继承了
object
的类以及该类的子类, 都是新式类 (Python3中统一都是新式类) - 在 Python3 中如果一个类没有继承任何类, 则默认会继承
object
类, 也就是Python3中所有的类都是新式类
在"Python3"中
class Default: # 默认继承"object"
pass
print(Default.__bases__) # (<class 'object'>,)
2.经典类
- 没有继承
object
的类以及该类的子类, 都是经典类 (只有Python2中才区分新式类和经典类) - 在 Python2 中如果一个类没有继承任何类, 它不会继承
object
类, 所以Python2 中才有经典类
在"Python2"中
class Default(object): # 新式类
pass
class Animal: # 经典类
pass
"Python2"中"print"语法
print Default.__bases__ # (<class 'object'>,)
print Animal.__bases__ # ()
ps : 新式类与经典类的属性查找顺序是不一样的
五.继承与抽象
-
继承描述的是子类与父类之间的关系,是一种什么是什么的关系
-
要找出这种关系,必须先抽象再继承,抽象即抽取类似或者说比较像的部分
1.抽象
- 将佩奇和乔治两对象比较像的部分抽取成类
- 将人,鸭,猪这三个类比较像的部分抽取成父类
- 抽象最主要的作用是划分类别(可以隔离关注点,降低复杂度)
2.继承
- 基于抽象的结果,通过编程语言去实现它,肯定是先经历抽象这个过程,才能通过继承的方式去表达出抽象的结构
- 继承的应用
class People(object):
school = "蟹堡王餐厅"
def __init__(self,name,age,sex):
self.name = name
self.age = age
self.sex = sex
class Staff(People):
def sell(self):
print(f"{self.name}正在卖蟹堡")
class Boss(People):
def payoff(self,obj,money):
print(f"{self.name}给{obj.name}发了{money}元工资")
obj.money = money
S1 = Staff("海绵宝宝",20,"male")
B1 = Boss("蟹老板",18,"male")
S1.sell() # 海绵宝宝正在卖蟹堡
B1.payoff(S1,300) # 蟹老板给海绵宝宝发了300元工资
print(S1.money) # 300
六.Python为类内置的特殊属性 (了解)
[类名].__name__ # 类的名字(字符串)
[类名].__doc__ # 类的文档字符串
[类名].__base__ # 类的第一个父类(在讲继承时会讲)
[类名].__bases__ # 类所有父类构成的元组(在讲继承时会讲)
[类名].__dict__ # 类的字典属性
[类名].__module__ # 类定义所在的模块
[类名].__class__ # 实例对应的类(仅新式类中)
七.类的派生
八.菱形继承问题
面说到Python支持多继承, 但新式类与经典类的属性查找顺序是不一样的