1 继承
继承:子类继承父类。继承是一种创建新类的方式。
2 继承的顺序
-
因为python支持多继承,所以有时候不得不考虑继承的顺序。
-
Python类如果继承多个类,寻找类的方法有两种,分别是:广度优先和深度优先。
其中python3和python2中的新式类,采用的是广度优先。
python2中的经典类,采用的是深度优先。
class A:
def test(self):
print("test from A")
class B(A):
# def test(self):
# print("test from B")
pass
class C(A):
def test(self):
print("test from C")
class D(B):
# def test(self):
# print("test from D")
pass
class E(C):
def test(self):
print("test from E")
class F(D,E):
# def test(self):
# print("test from F")
pass
f1=F()
f1.test()
#print(F.mro())
python3新式类的顺序为:F->D->B->E->C->A->object
python2经典类的顺序为:F->D->B->A->E->C
3 继承原理
python是如何实现继承的,当你写完class的定义(继承关系)以后,python会计算出一个MRO(Method Resolution Order 方法解析顺序)表,本质上就是一个保存着所有基类的线性关系顺序表。
>>>F.mro() #F.__mro__
[<class '__main__.F'>, <class '__main__.D'>, <class '__main__.B'>, <class '__main__.E'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>]
注意:__mro__属性只有在新式类中才有。经典类是没有的
为了实现继承,python会在MRO列表上从左到右开始查找基类,直到找到第一个匹配这个属性的类为止。
而这个MRO列表的构造是通过一个C3线性化算法来实现的。MRO列表实际上就是合并所有父类的MRO列表并遵循如下三条准则:
- 子类先于父类被检查
- 多个父类会根据它们在列表中的顺序
- 如果下一个类存在两个合法的选择,选择第一个父类
4 子类调用父类的方法
- 父类名.父类的方法()
(严格来说,只能算是一个类调用另一个类中的函数。如果去掉继承关系,并不影响最后的结果)
class People:
def __init__(self,name,age,sex):
self.name=name
self.age=age
self.sex=sex
def walk(self):
print("People is walking")
class Chinses(People):
def __init__(self,name,age,sex):
People.__init__(self,name,age,sex)
def walk(self):
People.walk(self)
print("walk from Chinese")
c=Chinses("egg",20,None)
c.walk()
结果:
People is walking
walk from Chinese
- super
在python2中,必须写成super(本类名,self).__init__(...)
在python3中,可以写成上述形式,也可写成super().__init__(...)
super()可以理解为父类的一个对象,super().__init__(...)也就是父类对象调用绑定方法。
class People:
def __init__(self,name,age,sex):
self.name=name
self.age=age
self.sex=sex
def walk(self):
print("People is walking")
class Chinses(People):
def __init__(self,name,age,sex):
super(Chinses,self).__init__(name,age,sex) #super(Chinses,self).__init__(name,age,sex)
def walk(self):
super().walk()
print("walk from Chinese")
c=Chinses("egg",20,None)
c.walk()
结果:
People is walking
walk from Chinese
使用super调用的所有属性,都是从MRO列表当前的位置往后。
5 多态和多态性
5.1 多态
多态:就是一个事物的多个形态。如继承。
如 动物有多种形态,猪、狗、猫。
import abc
class Animal(metaclass=abc.ABCMeta):
@abc.abstractclassmethod
def run(self):
pass
class Pig(Animal):
def run(self):
print("Pig is running")
class Dog(Animal):
def run(self):
print("Dog is running")
class Cat(Animal):
def run(self):
print("Cat is running")
5.2 多态性
5.2.1 什么是多态性
多态性是指具有不同功能的函数可以使用相同的函数名,这样就可以用一个函数名调用不同的内容。
def func(animal):
animal.run()
func(Pig())
func(Dog())
func(Cat())
结果:
Pig is running
Dog is running
Cat is running
总结:
- 多态性是“一个接口(函数func),多种实现”。
- 多态的概念是在定义时,多态性是在调用时。
5.2.2 多态的好处
其实python本身是支持多态的,这样处理的好处:
- 增加了程序的灵活性
以不变应万变,不论对象千变万化,使用者都是同一种形式去调用,如func(animal)。 - 增加了程序的可扩展性
只要后续写的类继承了Animal类,就都有run()函数。使用时调用func(animal),其他都不用改变。