python白鹅类型_python之接口:从协议到抽象基类

前言:在本章节中,新增一个白鹅类型,用于区别鸭子类型;另外,抽象基类的知识也表明,抽象基类,是用于构建框架,在遇到问题的时候首选通过别的方式实现,而不是抽象基类的方式。

1 鸭子类型和白鹅类型:这是两种编程风格,有很大的不同

鸭子类型:在这种编程风格中,我不太关心对象的类型,而是关注对象实现了何种方法,也就是说,对象的类型不再由父类决定,而是由方法决定。因此,鸭子类型风格时,不用通过检查参数、类型什么来判断对错,只需要判断方法是否正确实现即可,反应到

代码上就是没有N多ifelseifelse,而是只有try except

白鹅类型:这个编程风格是关于抽象基类的编程,相关内容有抽象基类,虚拟子类等,可以使用isinstance。

2 python中的接口和协议

协议是非正式的接口,是让python这种动态类型语言实现多态的方式;对象公开的方法的子集,让对象可以扮演不同的角色,所谓文件类对象和可迭代对象就是这个意思,这不是指某个类,而是指一个角色。

协议和继承没有关系,一个类可以实现多个协议,这样就会有多个角色身份。

3 序列协议

python对序列协议的支持特别周全,貌似很喜欢序列。

当实现了__getitem__特殊方法时,就足够访问元素、迭代和使用in运算符了。虽然没有__iter__方法,但是当发现有__getitem__时,python会自己调用它,从0开始,尝试迭代对象(这

是一种后备机制);而且没有实现__contains__方法,但是python因为有__getitem__用来迭代,因此也可以用于in运算符,查看是否有指定的元素。

python对待序列协议这种形式实现迭代,是对支持鸭子类型的极端表现,为了实现迭代也是拼了(为了实现迭代,解释器会调用两个不同的方法,即__iter__和__getitem__)。

4 序列的动态性:猴子补丁

当在运行的时候,突然发现类缺少了实现某个协议,此时可以将该协议实现,修改了类或模块,不改动源码,这种技术叫猴子补丁,也说明了协议的动态性。

5 定义抽象基类子类和定义新抽象基类

isinstance和issubclass,用于白鹅类型,检查抽象基类会更灵活。

定义了抽象基类子类之后,必须实现抽象基类中的接口。这也侧面验证了那句话,抽象基类就是接口。如果不实现,抽象基类会检查子类,就会报错。

标准库中有很多抽象基类,大部分在collections.abc模块中定义,numbers中有一些。

关于abc模块,

有两个,一个是是上面说的,一个是abc.ABC类,每个抽象基类都依赖这个类,当定义新抽象基类的时候才需要导入它。

定义抽象基类语法:继承abc.ABC,抽象方法需要用装饰器@abstractmethod装饰,然后还有其他三个装饰器,@abstractclassmethod,@abstractstaticmethod,@abstractproperty,但是从python3.3开始就废弃了这三个,因为装饰器可以在@abstractmethod上面堆叠。堆叠的时候一定要记住@abstractmethod在最下面。

抽象基类中也可以有具体方法,这个是跟C++不同的地方。

6 虚拟子类

白鹅类型的一个特征是,即使不继承,也可以通过注册把一个类注册为抽象基类的虚拟子类,但是这么做,默认我们实现了抽象基类的接口,python会相信,然后在运行的时候在做检查。

注册方法:有两种方法,一种是装饰器,一种是函数调用模式。前者是在定义类名上加装饰器@类名.register

>@A.register #将Test注册为A的虚拟子类

>class Test:

但是这种装饰器模式只能在python3.3之后的版本,如果是 3.3或者之前的版本,就只能是使用后者了。

在类定义完成的下方,加上A.register(Test),同样完成注册虚拟子类。

7 无需注册的虚拟子类

Alex提出, 有时候即使不注册,抽象基类也能把一个类识别为虚拟子类,情况如下:

某个类,实现了__len__方法,调用issubclass(该类实例,abc.Sized)时候返回True,这是因为abc.Sized实现了一个__subclasshook__的方法,在这个方法中,只要某个类实现了__len__,就是abc.Sized的虚拟子类。但标准库中好像就这一个。而自定义的抽象基类中,一般情况下也没必要是实现这个方法。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值