《流畅的Python》7-白鹅协议和抽象基类

这章主要讲的是 Python 风格下的协议和接口思想,不是很好归纳,搬运了一下书上的介绍。Python 里面没有给出类似 Java 中的interface的官方用法。

本章讨论的话题是接口:从鸭子类型的代表特征动态协议,到使接口更明确、能验证实现是否符合规定的抽象基类(Abstract Base Class,ABC)。
本章先说明 Python 社区以往对接口的不严谨理解:部分实现接口通常被认为是可接受的。我们将通过几个示例强调鸭子类型的动态本性,从而澄清这一点。

接着,对抽象基类做了介绍,还为 Python 编程的一个新趋势下了定义。本章余下的内容专门讲解抽象基类。首先,本章说明抽象基类的常见用途:实现接口时作为超类使用

然后,说明抽象基类如何检查具体子类是否符合接口定义,以及如何使用注册机制声明一个类实现了某个接口,而不进行子类化操作。最后,说明如何让抽象基类自动“识别”任何符合接口的类——不进行子类化或注册。

协议是非正式的

协议是非正式的,只由文档和约定定义,不具备强制性。
白鹅协议(goose typing)
和鸭子协议(duck typing)不同,鸭子协议关注多态性,
不关注类型,只关注方法和接口的相似性。
白鹅协议关注继承,只要是abc的子类,就可以认为是isinstance(abc)

序列协议为例,假设我们想实现迭代以及in运算,通常需要__iter____contains__方法,但事实上只实现__getitem__方法也可以。Python 会设法用迭代,通过__getitem__去实现__iter____contains__的方法,从而实现in运算。这说明实现部分协议是可行的。

猴子补丁

使用模板的时候,用修改自己的模板而不去修改源码去实现接口的方法叫做猴子补丁。这和不推荐自己写抽象基类有相似的思想。

抽象基类

  • 直接继承

    直接继承需要实现抽象基类的所有虚函数。

  • 注册类(register)

    注册类语法:@抽象基类名.register
    注册类不需要完全实现抽象基类的所有虚函数,某种程度上来说更加灵活。

写了三个类比较:

from abc import ABCMeta, abstractmethod

'''
最简单实现一个抽象类的办法就是继承 ABCMeta
Python 3.6 之前继承抽象基类需要写 metaclass=
'''

class Myabc (metaclass=ABCMeta):
    @abstractmethod
    def read():
        pass

    @abstractmethod
    def print():
        pass

class sample_1(Myabc):
    def read():
        pass

    def print():
        pass

class sample_2(Myabc):
    def read():
        pass

@Myabc.register
class sample_3():
    def read():
        pass
    def read2():
        pass


if __name__ == '__main__':
    test_1=sample_1()
    # test_2=sample_2() 没有完全实现虚函数,报错
    test_3=sample_3()
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值