day-25-类的继承顺序-父类对子类的约束-多态-队列和栈

一、类的继承顺序

只要继承object类就是新式类

不继承object类的都是经典类

 

在python3 中所有的类都继承object类,都是新式类

在python2 中不继承object的类都是经典类

继承object类的就是新式类

 

经典类:在py3中不存在,在py2中不主动继承object类

 

 

父类对子类的约束

抽象类:是一个开发的规范,约束它的所有子类必须实现一些和它同名的方法

列如:支付程序。

  • 微信支付 URL链接,告诉你参数什么格式

    • { ' username ' : ' 用户名 ' , ' money ' : 200 }

  • 支付宝支付 URL链接,告诉你参数什么格式

    • { ' uname ' : ' 用户名 ' , ' price' : 200 }

方法一:

day-25-类的继承顺序-父类对子类的约束-多态-队列和栈

class Payment:  # 这是个抽象类
    def pay(self, money):
        '''
        只要你见到了项目中有这种类,你要知道你的子类中必须实现和pay同名的方法
        '''
        raise NotImplementedError('请在类中重写重名pay类方法') # 主动抛异常
​
class WeChat(Payment):
    def __init__(self, username):
        self.username = username
​
    def pay(self, money):  # pay方法名字不能改变
        dic = {'username': self.username, 'money': money}
        '''
        调用微信支付 url连接 把dic传过去
        '''
        print(f'{self.username}通过微信充值了{money}')
​
class Alipay(Payment):
    def __init__(self, username):
        self.username = username
​
    def pay1(self, money):
        dic = {'uname': self.username, 'price': money}
        ''''
        调用支付宝支付 url连接 把dic传过去
        '''
        print(f'{self.username}通过支付宝充值了{money}')
​
# 归一化设计:同事或用户使用此类时,直接调用pay函数传参,不用自己创建对象
​
def pay(username, money, kind):
    if kind == 'WeChat':
        obj = WeChat(username)
    elif kind == 'Alipay':
        obj = Alipay(username)
    obj.pay(money)
​
pay('小杨', 200, 'WeChat')
​
# 当支付宝的pay方法名字发生改变时
pay('小杨', 200, 'Alipay')
​
# 输出
小杨通过微信充值了200
报错:NotImplementedError: 请在类中重写重名pay类方法

day-25-类的继承顺序-父类对子类的约束-多态-队列和栈

 

方法二:实现抽象类的另一种方式,约束力强,依赖abc模块

day-25-类的继承顺序-父类对子类的约束-多态-队列和栈

from abc import ABCMeta, abstractmethod
​
class Payment(metaclass=ABCMeta):  # 这是个抽象类
    @abstractmethod
    def pay(self, money):
        pass
​
class WeChat(Payment):
    def __init__(self, username):
        self.username = username
​
    def pay(self, money):  # pay方法名字不能改变
        dic = {'username': self.username, 'money': money}
        '''
        调用微信支付 url连接 把dic传过去
        '''
        print(f'{self.username}通过微信充值了{money}')
​
class Alipay(Payment):
    def __init__(self, username):
        self.username = username
​
    def pay1(self, money):
        dic = {'uname': self.username, 'price': money}
        ''''
        调用支付宝支付 url连接 把dic传过去
        '''
        print(f'{self.username}通过支付宝充值了{money}')
​
# 当支付宝的pay名字发生变化的时候
Alipay('xiao')      # 这种方法在实例化对象的时候就会报错提示
​
# 输出
TypeError: Can't instantiate abstract class Alipay with abstract method pay

day-25-类的继承顺序-父类对子类的约束-多态-队列和栈

 

三、多态

一个类型表现出来的多种状态:

  • 同一个对象,多种形态。python默认支持多态

day-25-类的继承顺序-父类对子类的约束-多态-队列和栈

def func(count):        # 这里的count可以是str、int、list、dict等等....count就是多态的
    print(count)
​
​
func('abc')
func(12345)
func([1, 2, 3, 4])
func({'a': 1, 'b': 2})
# 输出
abc
12345
[1, 2, 3, 4]
{'a': 1, 'b': 2}

day-25-类的继承顺序-父类对子类的约束-多态-队列和栈

 

而在Java的情况下:

  • 一个参数必须指定类型

  • 所以如果想两个类型的对象都可以传,那么必须让着两个继承自一个父类,在指定类型的时候使用父类来指定

  • 在java或者c#定义变量或者给函数传值必须定义数据类型,否则就报错。

def func(int a):
    print('a必须是数学')

 

  • 而类似于python这种弱定义类语言,a可以是任意形态(str,int,object等等)。

def func(a):
    print('a是什么都可以')

 

python伪代码实现Java或C的多态

day-25-类的继承顺序-父类对子类的约束-多态-队列和栈

class F1:
    pass
​
​
class S1(F1):
    
    def show(self):
        print 'S1.show'
​
​
class S2(F1):
    
    def show(self):
        print 'S2.show'
​
​
# 由于在Java或C#中定义函数参数时,必须指定参数的类型
# 为了让Func函数既可以执行S1对象的show方法,又可以执行S2对象的show方法,所以,定义了一个S1和S2类的父类
# 而实际传入的参数是:S1对象和S2对象
​
def Func(F1 obj):
"""Func函数需要接收一个F1类型或者F1子类的类型"""
​
    print obj.show()
    
​
s1_obj = S1()
Func(s1_obj)  # 在Func函数中传入S1类的对象 s1_obj,执行 S1 的show方法,结果:S1.show
​
s2_obj = S2()
Func(s2_obj)  # 在Func函数中传入Ss类的对象 ss_obj,执行 Ss 的show方法,结果:S2.show

day-25-类的继承顺序-父类对子类的约束-多态-队列和栈

 

鸭子类型

在python中,有一句谚语,你看起来像鸭子,那么你就是鸭子。

对相同的功能设定了相同的名字,这样方便开发,这两个方法就可以互成为鸭子类型。

比如:str、tuple、list 都有index方法,这就是互称为鸭子类型

day-25-类的继承顺序-父类对子类的约束-多态-队列和栈

class A:
    def f1(self):
        print('in A f1')
    
    def f2(self):
        print('in A f2')
​
​
class B:
    def f1(self):
        print('in A f1')
    
    def f2(self):
        print('in A f2')
        
obj = A()
obj.f1()
obj.f2()
​
obj2 = B()
obj2.f1()
obj2.f2()
# A 和 B两个类完全没有耦合性,但是在某种意义上他们却统一了一个标准。
# 输出
in A f1
in A f2
in A f1
in A f2

day-25-类的继承顺序-父类对子类的约束-多态-队列和栈

 

四、队列和栈、自定义Pickle

上一篇:各个手机绑PAY数量


下一篇:浅谈Python鸭子类型