Python中的abc模块

文章目录

  • Python中的abc模块
    • 前言
    • 判断类型
    • isinstance实现原理
    • 实现ABC类
    • 其他基类
    • 总结

前言

在《抽象基类(ABC)》中,基于C++讲述抽象基类。尽管Python设计上以鸭子类型为主,但仍有抽象基类(ABC)的一席之地,它被封装在了abc模块中供程序员使用。

abc模块有以下两个主要功能:

  • 某种情况下,判定某个对象的类型,如:isinstance(a, Sized)
  • 强制子类必须实现某些方法,即ABC类的派生类

判断类型

当我们判断一个对象是否存在某个方法时,可以使用内置方法hasattr()

class A(object):def __len__(self):passif __name__ == "__main__":a = A()print("存在__len__方法" if hasattr(a, "__len__") else "没有__len__方法")# 输出:
存在__len__方法

但在Python中,使用hasattr()并非优雅解法,这里建议isinstance()。

abc模块中定义了Sized类,利用Sized可以判断一个对象里是否存在__len__方法,即:可否对这个对象使用len()函数。

from collections.abc import Sizedclass A(object):def __len__(self):passif __name__ == "__main__":a = A()print("存在__len__方法" if isinstance(a, Sized) else "没有__len__方法")# 输出:
存在__len__方法

isinstance实现原理

让我们看看Sized类的源码:

class Sized(metaclass=ABCMeta):__slots__ = ()@abstractmethoddef __len__(self):return 0@classmethoddef __subclasshook__(cls, C):if cls is Sized:return _check_methods(C, "__len__")return NotImplemented

Sized类改写了__subclasshook__魔法方法,使其可以通过isinstance()判断对象是否含有__len__方法。同时,这个类必须基于元类abc.ABCMeta。我们也可以依葫芦画瓢,实现一个用来判断对象是否存在greet()函数的类,尽管并不严谨:

import abcclass A(metaclass=abc.ABCMeta):@classmethoddef __subclasshook__(cls, subclass):# 存在greet()返回True,不存在返回Falseif hasattr(subclass, "greet"):return Truereturn Falseclass B(object):def greet(self):  # 定义了greet()方法passclass C(object):  # 没有greet()方法passclass D(B):  # 继承自B类,因此继承了greet()方法passif __name__ == "__main__":b = B()c = C()d = D()print(isinstance(b, A))  # Trueprint(isinstance(c, A))  # Falseprint(isinstance(d, A))  # True

注意,此时A类可以被实例化,因为它还不是抽象基类。

实现ABC类

C++中利用纯虚函数实现抽象基类,Python中写法如下:

import abcclass A(metaclass=abc.ABCMeta):# 利用装饰器修饰greet()@abc.abstractmethoddef greet(self):print("hell world")if __name__ == "__main__":a = A()

解释器如期抛错:

TypeError: Can't instantiate abstract class A with abstract methods greet

这是因为A类现在就是一个抽象基类了,不可以被实例化,同时,它的子类还必须实现greet()方法,否则实例化子类时解释器也要报错:

import abcclass A(metaclass=abc.ABCMeta):@abc.abstractmethoddef greet(self):passclass B(A):def greet(self):passclass C(A):passif __name__ == "__main__":b = B()  # 正常实例化c = C()  # 解释器抛错# 输出:
# C类中没有定义greet()方法导致的报错
Traceback (most recent call last):File "xxx", line xxx, in <module>c = C()
TypeError: Can't instantiate abstract class C with abstract methods greet

其他基类

abc模块中还有实现了其他抽象基类,可以用来判断类型或是继承方法,这里不做详述了:

__all__ = ["Awaitable", "Coroutine","AsyncIterable", "AsyncIterator", "AsyncGenerator","Hashable", "Iterable", "Iterator", "Generator", "Reversible","Sized", "Container", "Callable", "Collection","Set", "MutableSet","Mapping", "MutableMapping","MappingView", "KeysView", "ItemsView", "ValuesView","Sequence", "MutableSequence","ByteString",]

文件所在路径:…lib\_collocetions_abc.py

总结

  • abc模块中定义的类兼顾了继承抽象基类与鸭子类型的设计方式。你既可以通过继承Sized来拥有__len__方法,此时instance(对象, Sized)返回True;也可以在自己设计的类中实现__len__instance(对象, Sized)仍然返回True。

  • 对抽象基类来说,需要用到装饰器 @abc.abstractmethod;对于鸭子类型来说,需要重写__subclasshook__魔法方法。

  • 以上都是基于元类abc.ABCMeta实现的。顺便提醒,注意import abcfrom collections import abc各自的区别。

Python中的abc模块相关推荐

  1. python是什么模块,python中什么是模块

    ## re模块 众多编程语言都为正则表达式的使用设置了标准库,Python也不例外.在Python中使用re模块来操作正则表达式的匹配.下面我们一起学习re模块的用法. ### 使用re还是compi ...

  2. python中调用什么模块的什么函数来实现求实数平方根_python语言基础与应用答案...

    python语言基础与应用答案 python3不再区分整数和长整数,统一为()类型. python可以使用(____)函数打开文件,这个函数默认的打开模式为(____). a=[3]alist=[1, ...

  3. python中callable_Python abc.Callable方法代码示例

    本文整理汇总了Python中collections.abc.Callable方法的典型用法代码示例.如果您正苦于以下问题:Python abc.Callable方法的具体用法?Python abc.C ...

  4. python中的numpy模块

    参考  python中的numpy模块 - 云+社区 - 腾讯云 目录 NumPy 教程 学习本教程前你需要了解 NumPy 应用 相关链接 NumPy 安装 1.使用已有的发行版本 2.使用 pip ...

  5. 介绍Python中的__future__模块

    这篇文章主要介绍了介绍Python中的__future__模块,__future__模块使得在Python2.x的版本下能够兼容更多的Python3.x的特性,需要的朋友可以参考下 Python的每个 ...

  6. python中的logging记录日志_[ Python入门教程 ] Python中日志记录模块logging使用实例...

    python中的logging模块用于记录日志.用户可以根据程序实现需要自定义日志输出位置.日志级别以及日志格式. 将日志内容输出到屏幕 一个最简单的logging模块使用样例,直接打印显示日志内容到 ...

  7. python使用教程cmd啥意思-Python 中的cmd模块学习

    Python中的cmd模块类型提供了一个创建命令行解析器的框架.简单的来说,可以继承Cmd来创建命令行界面,然后对所有想处理的命令command执行do_command方法.默认情况下,它使用read ...

  8. python中的绘图模块turtle的使用

    python中的绘图模块turtle的使用(7-20190125) 文章目录: 还是从一个有趣的小应用开始,turtle的骚操作吧 最近小猪配齐比较流行,下面用turtle绘制一个粉红色的小猪猪吧-- ...

  9. linux系统python截图不显示中文_Linux运维知识之解决linux系统下python中的matplotlib模块内的pyplot输出图片不能显示中文的问题...

    本文主要向大家介绍了Linux运维知识之解决linux系统下python中的matplotlib模块内的pyplot输出图片不能显示中文的问题,通过具体的内容向大家展现,希望对大家学习Linux运维知 ...

  10. Python中的random模块

    Python中的random模块用于随机数生成,对几个random模块中的函数进行简单介绍.如下: random.random() 用于生成一个0到1的随机浮点数.如: import random r ...

最新文章

  1. 实例讲解决策树分类器
  2. 子元素绝对定位absolute后,自动撑开宽度
  3. django博客项目8:文章详情页
  4. 解决ASP.NET AJAX在frame及iframe中跨域访问的问题
  5. 【SpringBoot】SpringBoot、ThemeLeaf 官方文档地址
  6. 论发展的十大关系。总结过去,正视未来!!!
  7. [Java]java反射随笔
  8. php 数组 定义 遍历,php针对数组的定义、遍历及删除
  9. windows7企业版 IIS常见问题
  10. Eureka常用配置
  11. idea 热部署时 tomcat处 没有update classes and resource 选项
  12. ElementUI以及uvie的图标使用和设置---SpringCloud Alibaba_若依微服务框架改造_ElementUI+uniapp_uview---工作笔记015
  13. Centos6.5下通过shell脚本快速安装samba服务器
  14. CocoaPods 2017最新、最快安装和使用说明
  15. 推动区块链基础设施建设,先要破解区块链发展“三高”难题
  16. html5 人物画像,人物头像画不准?掌握这五步,让你把人物头像画准,画像
  17. 华为人工智能atlasA800-9000物理服务器离线安装及CANN安装和MindSpore安装和Tensorflow安装
  18. Axure8 全选控制中继器里的checkbox
  19. 自旋锁为什么不适用于单处理器系统
  20. 记 PS2020 打开闪退问题

热门文章

  1. Flex VideoPlayer组件 属性详解
  2. 【5G系列】MAC (Medium Access Control)协议详解
  3. js中进行字符串替换的方法
  4. 在阿里,一个完整的机器学习项目是这样运作的。
  5. ADB介绍—— 配置ADB环境变量
  6. PHP 生成带文字图片
  7. OSG绘制空间凹多边形以及透明效果的实现
  8. Java 点餐小程序源码带管理后台(免费分享)
  9. js实现简单的有序map
  10. 2020计算机网络练习题记录(1)