继承 和多态
继承
什么是继承?
继承是一种创建新的类的方式,新创建的叫子类,继承的叫父类、超类、基类。
特点:子类可以使用父类的属性(特征、技能)
继承是类与类之间的关系
为什么要继承?
- 减少代码冗余、提高重用性
如何使用继承?
继承分为单继承和多继承
我们先看单继承
class A(object):
def pp(self):
print('pp A')
class B(A):
def pp(self):
super().pp()
print("pp B")
b = B()
b.pp()
#pp A
#pp B
super()常用的方法是在__ init __()方法中确保父类被正确的初始化了:
super(cls,inst).__ init__() #cls,init 可以省略
class A(object):
def __init__(self):
self.x = 1
class B(A):
def __init__(self):
super(B,self).__init__()
self.x = self.x +1
print(self.x)
b = B()
#2
也可以直接调用父类的一个方法 :
A.__ init__(self)
class A(object):
def __init__(self):
self.x = 1
class B(A):
def __init__(self):
A.__init__(self)
self.x = self.x +1
print(self.x)
b = B()
#2
多继承例子:
class A(object):
def __init__(self):
print("Enter A")
class B(A):
def __init__(self):
print('Enter B')
super(B,self).__init__()
print('Leave B')
class C(A):
def __init__(self):
print('Enter C')
super(C, self).__init__()
print('Leave C')
class D(B,C):
def __init__(self):
print('Enter D')
super(D,self).__init__()
print("Leave D")
d = D()
'''
Enter D
Enter B
Enter C
Enter A
Leave C
Leave B
Leave D
'''
使用__ bases__方法可以获取子类继承的类
class Parent2():
print('我是第二个爹')
class Parent():
print('我是第一个爹')
class SubClass(Parent, Parent2):
print('我是子类')
print(SubClass.__bases__)
#注意,如果sub = SubClass(),sub是没有__bases__方法的
'''
我是第二个爹
我是第一个爹
我是子类
(<class '__main__.Parent'>, <class '__main__.Parent2'>)
'''
super()的用法:
super()的本质
先说说python中如何实现继承———对于你定义的每一个类,Python会计算出一个所谓的方法解析顺序(MRO)列表。 这个MRO列表就是一个简单的所有基类的线性顺序表。为了实现继承,Python会在MRO列表上从左到右开始查找基类,直到找到第一个匹配这个属性的类为止。
而这个MRO列表的构造是通过一个C3线性化算法来实现的。 我们不去深究这个算法的数学原理,它实际上就是合并所有父类的MRO列表并遵循如下三条准则:
子类会先于父类被检查
多个父类会根据它们在列表中的顺序被检查
如果对下一个类存在两个合法的选择,选择第一个父类
虽然名义上来说super是用来调用父类中的方法,但是super实际上是在MRO表中找到下一个匹配的类。super原型如下:
def super(cls, inst):
mro = inst.__class__.mro()
return mro[mro.index(cls) + 1]
两个参数 cls 和 inst 分别做了两件事:
inst 负责生成 MRO 的 list
通过 cls 定位当前 MRO 中的 index, 并返回 mro[index + 1]
关于super的概念大家不用深究,只要掌握其语法会用了就行。
多态
一个操作的意义取决于被操作对象类型,相同的消息给与不同的对象会引发不同的动作。
多态意味着变量并不知道引用的对象是什么,根据引用对象的不同,表现不同的行为方式。
在处理多态对象时,只需要关注他的接口即可。
同一个操作作用于不同的对象,可以有不同的解释,产生不同的执行结果。
注意:多态和多态性是两种不同的概念
多态:
传统意义上的多态指一类事物有多种形态,比如动物类,可以有猫,狗,猪等等。(一个抽象类有多个子类,因而多态的概念依赖于继承)
用代码表示如下:
import abc
class Animal(metaclass=abc.ABCMeta): #同一类事物:动物
@abc.abstractmethod
def talk(self):
pass
class Cat(Animal): #动物的形态之一:猫
def talk(self):
print('say miaomiao')
class Dog(Animal): #动物的形态之二:狗
def talk(self):
print('say wangwang')
class Pig(Animal):
def talk(self):
print('say aoao')
多态性:
多态性是指具有不同功能的函数可以使用相同的函数名,这样就可以用一个函数名调用不同内容的函数。在面向对象方法中一般是这样表述多态性:向不同的对象发送同一条消息,不同的对象在接收时会产生不同的行为(即方法)。也就是说,每个对象可以用自己的方式去响应共同的消息。所谓消息,就是调用函数,不同的行为就是指不同的实现,即执行不同的函数。
import abc
class Animal(metaclass=abc.ABCMeta): #同一类事物:动物
@abc.abstractmethod
def talk(self):
pass
class Cat(Animal): #动物的形态之一:猫
def talk(self):
print('say miaomiao')
class Dog(Animal): #动物的形态之二:狗
def talk(self):
print('say wangwang')
class Pig(Animal):
def talk(self):
print('say aoao')
c=Cat()
d=Dog()
p=Pig()
def func(obj):
obj.talk()
func(c)
func(d)
func(p)
#say miaomiao
#say wangwang
#say aoao
综上可以说,多态性是 : 一个接口,多种实现
多态性的好处:
增加了程序的灵活性,以不变应万变,不论对象千变万化,使用者都是同一种形式去调用,如func(obj)
增加了程序额可扩展性,通过继承animal类创建了一个新的类,使用者无需更改自己的代码,还是用func(obj)去调用
小作业:
今天依旧没有新的小作业哦,第十二天的作业是综合性的哦~