多态的概念
多态指的是一类事物的多种形态,例如水有固态、液态、气态,动物有人、狗、猪,这是动物的不同形态。可能你会领悟,人狗猪不是继承于动物类吗?没错,多态在程序中的表现形式就是依赖于继承
多态性
那多态到底有什么特性呢?多态性指的是可以在不用考虑对象具体类型的前提下,直接使用对象下的方法,也就是说,继承同一个类的多个子类有相同的方法名,那么子类产生的对象就可以不用考虑具体的类型而直接调用对象的方法
举一个例子,动物有人狗猪,动物都会叫,那么人狗猪也都会叫,只不过叫的方式不同
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
class Animal:
pass
class People(Animal):
def speak(self):
print('say hello')
class Dog(Animal):
def speak(self):
print('汪汪汪')
class Pig(Animal):
def speak(self):
print('哼哼哼')
# peo、dog、pig都是动物, 只要是动物肯定有speak方法
# 于是我们可以不用考虑它们三者的具体是什么类型, 而直接使用
peo = People()
dog1 = Dog()
pig1 = Pig()
peo.speak()
dog1.speak()
pig1.speak()
但是美中不足的是,如果现在人的叫不写成 speak ,写成 talk,那么便无法遵循父类的方法去实现多态性,如果这三个都想实现叫的功能,父类要有,子类也要有,这显然很麻烦,并且这样写不能对子类有个强制性的限制,这个限制是子类必须有一个叫的功能,这个功能是 speak。于是要写一个解决方案,强制子类遵循父类的标准,有一个 abc 的模块,可以实现这个功能
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
import abc
class Animal(metaclass=abc.ABCMeta):
@abc.abstractmethod
def speak(self):
pass
class People(Animal):
# def speak(self):
# print('say hello')
# 写成talk便会报错
def talk(self):
print('say hello')
class Dog(Animal):
def speak(self):
print('汪汪汪')
class Pig(Animal):
def speak(self):
print('哼哼哼')
peo = People()
dog1 = Dog()
pig1 = Pig()
peo.speak()
dog1.speak()
pig1.speak()
# 运行
TypeError: Can't instantiate abstract class People with abstract methods speak
鸭子类型
但是上面所说的这些并不是 Python 所推崇的,Python 崇尚的是 “鸭子类型” ,即 “如果看起来像鸭子、叫声像鸭子而且走起路来也像鸭子,那么它就是鸭子”,
Python 程序员通常根据这种行为来编写程序。例如,如果想编写现有对象的自定义版本,可以继承该对象,也可以创建一个外观和行为像,但与它无任何关系的全新对象,后者通常用于保存程序组件的解耦合度
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
# 利用标准库中定义的各种‘与文件类似’的对象,尽管这些对象的工作方式像文件,但他们没有继承内置文件对象的方法
# 二者都像鸭子,二者看起来都像文件,因而就可以当文件一样去用
class TxtFile:
def read(self):
pass
def write(self):
pass
class DiskFile:
def read(self):
pass
def write(self):
pass
# 例2:其实大家一直在享受着多态性带来的好处,比如Python的序列类型有多种形态:字符串,列表,元组,多态性体现如下
# str,list,tuple都是序列类型
s=str('hello')
l=list([1,2,3])
t=tuple((4,5,6))
# 我们可以在不考虑三者类型的前提下使用s,l,t
s.__len__()
l.__len__()
t.__len__()
len(s)
len(l)
len(t)