1.归一化设计(接口类)
class AliPay: def __init__(self,name): self.name = name def pay(self,money): # 支付宝提供了一个网络上的联系渠道 print('%s通过支付宝消费了%s元'%(self.name,money)) class WeChatPay: def __init__(self,name): self.name = name def pay(self,money): # 微信提供了一个网络上的联系渠道 print('%s通过微信消费了%s元'%(self.name,money)) # 归一化设计 : 从原来的面向对象编程 -->面向函数编程.降低了用户的使用成本 def pay_func(person,money): #支付函数,总体负责支付 person.pay(money) #对应支付和对象要支付的金额 alex=AliPay("alex")
nezha=WeChatPay("nezha")
#alex.pay(200) #归一化设计,使用当前pay-func函数就不需要
#nezha.pay(100) #自己用对象去调用pay方法了,就像使用函数直接用
pay_func(alex,200) #pay-func传一个alex,传一个200就完事了
pay_func(nezha,100)
第二种写法归一化:
def pay_func(person,payway,money): #
if payway=="alipay":
per = AliPay(person)
elif payway=="wechatpay":
per=WeChatPay(person)
per.pay(money)
pay_func("alex","alipay",200)
pay_func("nazha","wechatpay",100)
#接口初成:手动报异常:NotImplementedError来解决开发中遇到的问题
抽象类
抽象类的特点:
必须在类定义的时候指定metaclass = ABCMeta
必须在要约束的方法上方加上@abstractmethod方法
# 支付途径 # 支付宝 微信 银行卡 nfc支付 #import abc #利用abc模块实现抽象类 from abc import ABCMeta,abstractmethod class Payment(metaclass=ABCMeta): # metaclass 元类 metaclass = ABCMeta表示Payment类是一个规范类 @abstractmethod #(定义抽象方) # @abstractmethod表示下面一行中的pay方法是一个必须在子类中实现的方法 def pay(self):pass #子类必须定义支付功能 # 规定:Payment 就是一个规范类,这个类存在的意义不在于实现实际的功能,而是为了约束所有的子类必须实现pay的方法
@abstractmethod def back(self):pass #子类必须定义退款功能 # Payment : 抽象类 # pay = Payment() # 抽象类: 不能实例化 class AliPay(Payment): # 抽象类主要就是作为基类/父类,来约束子类中必须实现的某些方法 def __init__(self,name): self.name = name def pay(self,money): # 支付宝提供了一个网络上的联系渠道 print('%s通过支付宝消费了%s元'%(self.name,money)) class WeChatPay(Payment): def __init__(self,name): self.name = name def pay(self,money): # 微信提供了一个网络上的联系渠道 print('%s通过微信消费了%s元'%(self.name,money)) class ApplePay(Payment): def __init__(self,name): self.name = name def pay(self,money): print('%s通过苹果支付消费了%s元'%(self.name,money)) def back(self): print('退款')
# 归一化设计 : 从原来的面向对象编程 -->面向函数编程.降低了用户的使用成本 def pay_func(person,payway,money): if payway == 'alipay': per = AliPay(person) elif payway == 'wechatpay': per = WeChatPay(person) elif payway == 'ApplePay': per = ApplePay(person) per.pay(money) pay_func('alex','alipay',200) pay_func('nazha','wechatpay',100) pay_func('宝元','ApplePay',100) bao = ApplePay('baoyuan')
接口
1. java 不支持多继承
python 支持多继承 :通过抽象类的多继承来实现复杂的规范
2.python
抽象类 : 抽象类中的方法可以写一些具体的py代码(规范)
单继承:都是定义规范的
多继承:都是定义规范的
3. java:
不支持多继承,新的概念 接口 Interface
和抽象类几乎一模一样的功能 :
只定义一个接口名字(基类名),内部定义子类必须实现的方法
接口支持多继承
接口内部的所有方法都不能写具体的代码,只能用pass代替
4.抽象类 :
单继承的形容,并且在单继承中可以在方法中写python代码
5.接口类 : 更接近java中的接口的概念
python中由于有了抽象类的多继承,不需要接口的概念了
一个基类写出来被子类多继承了 : 接口类
并且在方法中只写pass(你可以选择性的满足)
借用abc模块来实现接口
# 动物园 # 天鹅 : 飞 走 游泳 # 老虎 : 走 游泳 # 鹦鹉 : 飞 走 说话
from abc import ABCMeta,abstractmethod #引入模块
class Fly_Animal(metaclass=ABCMeta): @abstractmethod def fly(self): print('爷会飞')
class Swim_Animal(metaclass=ABCMeta): @abstractmethod def swim(self): pass
class Walk_Animal(metaclass=ABCMeta): @abstractmethod def walk(self): pass class Swan(Fly_Animal,Swim_Animal,Walk_Animal): def fly(self): super().fly() print('飞') def walk(self):print('走') def swim(self):print('游') class Tiger(Walk_Animal,Swim_Animal): def walk(self):print('走') def swim(self):print('游') class Parrot(Fly_Animal,Walk_Animal): def fly(self):print('飞') def walk(self):print('走') def talk(self):print('说') # 不同动物的相同行为是不能混为一谈 # 不同动物的相同行为的方法名字是必须一样
python2:两种类 经典类 新式类
经典类,经典类在基础的根如果什么都不写,表示继承xxx
在经典类中采用的是深度优先 遍历方案. 什么是深度优先. 就是一条路走到头. 然后再回来. 继续找下⼀一个
1.当类是经典类时,多继承情况下,会按照深度优先方式查找,没有MRO提示你顺序,没有super
2.当类是新式类时,需要主动继承object,多继承情况下,会按照广度优先方式查找
python3:只有一种类 新式类
新式类: 默认继承object类 # object 是所有类的父类
为什么可以不写__init__?
所有object中的类都是你自己不写也可以调用的
在python3中 所有的类都是新式类,所有的新式类的继承顺序都遵循C3算法,
可以使用类名.__mro__()这个方法来查看这个继承顺序
区别:python3.x和python2.x中的新式类有什么区别?
1,不需要主动继承object
2python3中的super()可以直接用,python2中使用必须传参数super(子类名,对象名).方法名
class A(object): def test(self): print('from A') class B(A): def test(self): print('from B') class C(A): def test(self): print('from C') class D(B): def test(self): print('from D') class E(C): def test(self): print('from E') class F(D,E): # def test(self): # print('from F') pass f1=F() f1.test() print(F.__mro__) #只有新式才有这个属性可以查看线性列表,经典类没有这个属性 #新式类继承顺序:F->D->B->E->C->A #经典类继承顺序:F->D->B->A->E->C #python3中统一都是新式类 #pyhon2中才分新式类与经典类
C3算法 - 钻石模型
每一个类的继承顺醋都是从基类向子类看
形成一个指向关系的顺序[当前类]+[父类的继承顺序]
进行一个提取
如果一个类出现在从左到右的第一个顺序上
并且没有出现在后面顺序中
或者出现在后面的顺序中了但是仍然是第一个,
那么就把这个类提取出来
继承小结
继承原理:
python到底是如何实现继承的,对于你定义的每一个类,python会计算出一个方法解析顺序(MRO)列 表,这个MRO列表就是一个简单的所有基类的线性顺序列表
(为了实现继承,python会在MRO列表上从左到右开始查找基类,直到找到第一个匹配这个属性的类为止。
而这个MRO列表的构造是通过一个C3线性化算法来实现的。我们不去深究这个算法的数学原理,它实际上就是合并所有父类的MRO列表并遵循如下三条准则:
1.子类会先于父类被检查
2.多个父类会根据它们在列表中的顺序被检查
3.如果对下一个类存在两个合法的选择,选择第一个父类)
继承的作用:
减少代码的重用
提高代码可读性
规范编程模式
几个名词:
抽象:抽象即抽取类似或者说比较像的部分。是一个从具题到抽象的过程。
继承:子类继承了父类的方法和属性
派生:子类在父类方法和属性的基础上产生了新的方法和属性
抽象类与接口类:
1.多继承问题
在继承抽象类的过程中,我们应该尽量避免多继承;
而在继承接口的时候,我们反而鼓励你来多继承接口
2.方法的实现
在抽象类中,我们可以对一些抽象方法做出基础实现;
而在接口类中,任何方法都只是一种规范,具体的功能需要子类实现
super是什么鬼
super()可以帮我们执行MRO中下一个父类的方法. 通常super()有两个使⽤的地方:
1. 可以访问父类的构造⽅方法
2. 当子类方法想调用父类(MRO)中的方法