Python | 多态
至今不是很理解,先把现有理解记录下,日后在编程过程中有了更深更正确的理解,再来更正。
本文记录在学习过程中听说了三种多态,下文使用的“第一种说法”等分类方法是为方便记录的、纯粹的个人分类。
目录:
一、我所见到的对多态的三种解释
二、鸭子模型
—————正文—————
一、我所见到的对多态的三种解释
1. 不同的子类对象,调用相同的父类方法,产生不同的执行结果
目的:增加代码的灵活性
以继承和重写父类方法为前提
是调用方法的技巧,不会影响到类的内部设计
class Dog(object): def __init__(self, name): self.name = name def play(self): print("%s jump jump play" % self.name) class XiaotianDog(Dog): def play(self): print("%s fly fly play" % self.name) class Person(object): def __init__(self, name): self.name = name def play_with_dog(self, dog): print("%s and %s happy happy play" % (self.name, dog.name)) dog.play() # 不同的对象,调用相同的方法,产生不同的结果 wangcai = Dog("wangcai") dawang = XiaotianDog("dawang") xiaoming = Person("xiaoming") # xiaoming.play_with_dog("wangcai") 错误啦 xiaoming.play_with_dog(wangcai) # 要传进去的是狗对象 xiaoming.play_with_dog(dawang)
2. 一个对象具有多种形态,在不同的环境中以不同的形态展示其功能,称该对象具有多态特征
多态发生在【继承】关系的基础之上
1 class Teacher(): 2 def teach(self): 3 print("teach---") 4 5 6 class Driver(): 7 def drive(self): 8 print("drive---") 9 10 11 class Man(Teacher, Driver): 12 def teach(self): 13 print("teach python") 14 15 def drive(self): 16 print("drive car") 17 18 19 class Demo(): 20 def travel(self, driver): 21 driver.drive() 22 23 def study(self,teacher): 24 teacher.teach() 25 26 27 # 创建一个 司机对象,来完成旅行开车这件事 28 d = Driver() 29 demo1 = Demo() 30 demo1.travel(d) 31 32 # 直接找到一个会开车的对象来完成开车这件事,不需要单独创建一个司机对象【多态的方法】 33 # 会开车的这个对象可能也会别的,不管,只要能开车就好了,说了这么多,上路不?哈哈哈哈 34 man = Man() 35 demo = Demo() 36 # man.drive() 37 demo.travel(man) 38 39 # 按照多态的思路,如果有个地方需要一个teacher,也可以直接传这个man 40 demo.study(man)
3. 为不同的基础形态(数据类型)提供相关接口的能力
接口:指的是函数或方法
如print函数为字符串、整数、列表等等不同的数据类型都提供了接口,只需要用一个print就可以支持所有的数据类型,
而不需要定义并调用不同的函数,如:print_str、print_int、print_list等
1 print("hello") 2 print(23) 3 print([1, 2, 3])
假设要编写一个程序,创建猫、狗、羊三种动物,分别对应吃鱼、骨头、草,就可以定义Cat/Dog/Sheep三个类,并各自定义eat的方法。
Cat.eat()对应猫吃,Dog.eat()对应狗吃,Sheep.eat()对应羊吃,这样每个对象都有一个eat方法的接口,支持本动物吃东西。
即:为三个不同的对象提供了相同的接口。
如果不使用多态,则需要每个动物对应各自特有的cat_eat()/dog_eat()/sheep_eat。
1 class Dog: 2 def eat(self): 3 print("我是狗,我吃骨头") 4 5 6 class Cat: 7 def eat(self): 8 print("我是猫,我吃鱼") 9 10 11 class Sheep: 12 def eat(self): 13 print("我是羊,我吃草") 14 15 16 def animal_eat(animal): 17 animal.eat() #不同的动物(数据、对象)使用相同的接口 18 19 20 animal_eat(Dog()) 21 animal_eat(Cat()) 22 animal_eat(Sheep()) 23 """ 24 执行代码,打印: 25 我是狗,我吃骨头 26 我是猫,我吃鱼 27 我是羊,我吃草 28 """
二、鸭子模型
被调用的类没有使用继承,但是在语法层面满足了调用关系
特殊的多态表现形式
不仅是方法,属性也可以有鸭子类型,如,你需要一个name属性,那给一个带那么属性的就可以了
多态:在形式上和调用上都满足所谓的多态的要求
鸭子模型:在调用关系上满足,但是在形式上不满足
1 # 要求:找一个人过来教某一样东西 2 class Teacher(): 3 def teach(self): 4 print("teach---") 5 6 7 class Man(Teacher): 8 # def teach(self): 9 # print("teach python") 10 11 def drive(self): 12 print("drive car") 13 14 15 class Demo(): 16 def study(self,teacher): 17 teacher.teach() 18 19 20 class TeachGame(): 21 def teach(self): 22 print("教打游戏") 23 24 25 # 找继承了Teacher父类中teach方法的man,可以过来教某事 26 d = Demo() 27 man = Man() 28 d.study(man) 29 30 # TeachGame这个类本身没有涉及继承,但是Dome的实例对象d,需要在study方法中执行的teach方法 正好在TeachGame中也存在 31 # 假当是多态的一个特殊形式 32 player = TeachGame() 33 d.study(player)
目前是傻傻分不清楚了。
【本文仅用于学习交流】