python学习笔记 day25 多态
1. 多态 -----python天生支持多态
多态:一个事物具有多种形态
from abc import abstractmethod,ABCMeta class Animal(metaclass=ABCMeta): # 事物---动物 @abstractmethod def talk(self): print("子类继承抽象类一定要实现该方法") class Person(Animal): # 动物的形态一-----人 def talk(self): print("子类Person中实现了该方法") class Dog(Animal): # 动物的形态二-----狗 def talk(self): print("Dog类中实现了抽象类中的方法")
2. 多态性
就是把继承自同一个抽象类的不同子类内实现的相同的方法,写一个归一化接口,可以在归一化接口这个函数中传不同的参数就可以完成不同的对象调用不同的函数完成不同的功能(虽然看起来调用的是同一个函数)因为继承了同一个抽象类,对子类的方法进行了规范约束;
from abc import abstractmethod,ABCMeta class Payment(metaclass=ABCMeta): @abstractmethod def pay(self,money): # 抽象类中定义的方法,必须在继承这个抽象类的子类方法中实现,规范子类的方法 pass class Wechat(Payment): # 继承了抽象类Payment def pay(self,money): print("使用微信支付了%s"% money) # 虽然都是继承自抽象类Payment,但是里面的pay()方法实现的内容是有所差别的 class Alipay(Payment): def pay(self,money): # 子类实现了所继承的抽象类中的方法 print("使用支付宝支付了%s"%money) def Pay(pay_obj,money): # 使用了归一化接口,只需要传一个对象,就可以调用不同对象的pay()方法,其实内部执行的是不同对象各自的方法,功能略有不同----->多态 pay_obj.pay(money) wechat=Wechat() alipay=Alipay() Pay(wechat,100) # 实现了接口类,可以完成使用一个Pay()函数,只要传入不同的参数就可以调用不同对象各自的pay()函数,执行的内容略有差别 Pay(alipay,200)
上面定义的Wechat 和 Alipay都是继承自抽象类Payment() 主要面向对象的开发规范,用来约束子类代码,就是子类内部都得实现pay()方法,接着实现了一个统一的接口Pay()传入不同的对象,从而调用不同对象各自的pay()方法,表面上好像执行的同一个Pay()函数,其实内部在执行不同对象各自的pay()方法,执行的内容有所差别(比如一个是使用微信支付,另一个使用支付宝支付),其实这里的obj就好像代表了多态,既可以代表Wechat类实例化的对象,也可以代表Alipay类实例化的对象,这就是多态;
其他强类型语言由于在传参数时必须指定类型,所以一般都需要定义一个父类,然后让子类去继承,归一化接口那里传参数写的类型就是父类名,接下来只要是继承这个父类的子类实例化的对象都可以作为参数传进去,这就是父类的多态(可以是这种子类的对象,也可以是那种子类的对象),但是python作为一门动态的强类型语言,是不需要在传参数时指定类型的,所以说python天生支持多态;
3. 鸭子类型
python不崇尚继承接口类或者抽象类 把相似的功能抽象出来放父类(抽象类或接口类)规范化子类代码,崇尚鸭子类型,就是两个类的某些功能很相似也没有把这部分相似的功能抽象出来放到父类中,而是在两个类中分别实现(体现在给函数传参时,只要这个函数有这个类似的方法就可以作为参数传进去)
比如说list和tuple这两种数据类型有很多相似的方法比如count,index,len 但是源码并没有把这两种类的相似的方法抽象出来放到父类中,然后让这两个类去继承父类的方法,而是在各自的类中分别实现了相应的方法,并且功能相似的方法都叫相同的名字,比如计算长度的len()---这是另外写的归一化接口,list tuple内部就是都把计算长度的方法命名为__len__() 然后在len() 外部函数中,统一调用了各自对象的__len__()方法:
class List(): def __len__(self): pass class Tuple(): def __len__(self): pass def len(obj): # 只要传来的对象obj有__len__()方法都可以传进来,比如List() 和 Tuple()类实例化的对象 都有__len__()方法,就是鸭子类型 obj.__len__() lis=List() tup=Tuple() len(lis) len(tup)
鸭子类型在不使用继承的情况下使用了多态: 参考自https://zh.wikipedia.org/wiki/%E9%B8%AD%E5%AD%90%E7%B1%BB%E5%9E%8B