1、继承的简单语法
继承指的是类与类之间的关系,继承的功能之一就是用来解决代码重用问题
继承是一种创建新类的方式,在python中,新建的类可以继承一个或多个父类,父类又可以成为基类或超类,新建的类称为派生类或子类
class People:
pass
class Male(People):
pass
print(Male.__bases__)
# (<class '__main__.People'>,)
__base__只查看从左到右继承的第一个子类,__bases__则是查看所有继承的父类,python支持多继承,用逗号分隔开多个继承的类
2、属性查找
2.1 派生
通过继承的方式创建一个新的类,会继承父类的所有属性,查找属性先从实例中找,然后去类中找,然后去父类中找。
子类也可以添加自己新的属性,或者在子类中重新定义父类中的属性,在调用时以子类为准,这就是派生。
2.2 继承的查找原理
为了实现继承,python会在MRO列表上从左到右开始查找,直到找到第一个匹配这个属性的类为止。
class People:
pass
class Male(People):
pass
print(Male.mro())
[<class '__main__.Male'>, <class '__main__.People'>, <class 'object'>]
Python中子类可以同时继承多个父类,如果继承了多个父类,那么属性的查找方式有两种,分别是:深度优先和广度优先
python3里统一都是新式类,按照广度优先的方式查找
2.2.1新式类和经典类
python2中才分经典类和新式类,没有继承object类的类以及该类的子类都是经典类,反之为新式类,python3中默认继承object类,都是新式类。
class People:
pass
print(People.__bases__)
(<class 'object'>,)
2.2.2 广度优先
最后再找最高层类
class A:
def test(self):
print('from A')
class B(A):
def test(self):
print('from B')
class C(A):
def test(self):
print('from C')
class D(B):
def test(self):
print('from D')
class E(C):
def test(self):
print('from E')
class F(D, E):
def test(self):
print('from F')
f1 = F()
print(F.mro())
# [<class '__main__.F'>, <class '__main__.D'>,
# <class '__main__.B'>, <class '__main__.E'>,
# <class '__main__.C'>, <class '__main__.A'>,
# <class 'object'>]
class A:
def test(self):
print('from A')
class B(A):
def test(self):
print('from B')
class C(A):
def test(self):
print('from C')
class H(A):
pass
class D(B):
def test(self):
print('from D')
class E(C):
def test(self):
print('from E')
class F(D):
def test(self):
print('from F')
class G(E):
pass
class I(F, H, G):
pass
print(I.mro())
[<class '__main__.I'>, <class '__main__.F'>, <class '__main__.D'>, <class '__main__.B'>, <class '__main__.H'>, <class '__main__.G'>, <class '__main__.E'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>]
3、子类调用父类的方法
在子类派生出的新方法中,往往需要重用父类的方法
有两种方式:
1、父类名.函数名(参数),不依赖继承,就是普通的父类函数调用。
class People:
def __init__(self, name, age, sex):
self.name = name
self.age = age
self.sex = sex
def run(self):
pass
class Student(People):
def __init__(self, name, age, sex, grade):
# self.name = name
# self.age = age
# self.sex = sex
People.__init__(self, name, age, sex) # 父类名+函数名
self.grade = grade
def learn(self):
pass
s1 = Student('xiaohong', 18, 'male', '3')
print(s1.grade)
2、super()方法
class People:
def __init__(self, name, age, sex):
self.name = name
self.age = age
self.sex = sex
def run(self):
pass
class Student(People):
def __init__(self, name, age, sex, grade):
# self.name = name
# self.age = age
# self.sex = sex
# People.__init__(self, name, age, sex) # 父类名+函数名
super().__init__(name, age, sex) # 没有self参数
self.grade = grade
def learn(self):
pass
s1 = Student('xiaohong', 18, 'male', '3')
print(s1.grade)
super是依赖继承的,即使没有继承关系,也会按照mro顺序表查找:
class A:
def test(self):
super().f1()
class B:
def f1(self):
print('from B')
class C(A,B):
pass
c = C()
c.test()
print(C.mro())
结果
from B
[<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <class 'object'>]
4、组合重用
组合指的是,在一个类中以另外一个类的对象作为数据属性,称为类的组合。
组合就是在对象中添加一个数据属性,指向另外一个类的对象。
意思就是把另外一个类的对象当作一项属性添加到属性中。
继承是一种’是’的关系,老师和学生是人,组合是一种“有”的关系,老师有课程,学生有老师。
当类之间有显著不同,并且较小的类是较大的类所需要的组件时,用组合比较好
class People:
def __init__(self, name, age, sex):
self.name = name
self.age = age
self.sex = sex
class Teacher(People):
def __init__(self, name, age, sex):
People.__init__(self, name, age, sex) # 继承重用
class Student(People):
def __init__(self, name, age, sex):
People.__init__(self, name, age, sex)
class Course:
def __init__(self, name, price):
self.name = name
self.price = price
student = Student('小明', 18, 'male')
teacher = Teacher('老李', 36, 'male')
# 为学生增加课程
python = Course('python', '3000')
student.course = python # 组合重用
print(student.course)
# <__main__.Course object at 0x000002A1F34C5160>
print(student.course.name)
# python
# 为老师增加学生
teacher.student = student
print(teacher.student)
# <__main__.Student object at 0x000001DC13CE50F0>
print(teacher.student.name)
# 小明