继承进阶

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)中的方法

原文地址:https://www.cnblogs.com/baoshuang0205/p/10004879.html