Python中的abc模块
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 abc
与from collections import abc
各自的区别。
Python中的abc模块相关推荐
- python是什么模块,python中什么是模块
## re模块 众多编程语言都为正则表达式的使用设置了标准库,Python也不例外.在Python中使用re模块来操作正则表达式的匹配.下面我们一起学习re模块的用法. ### 使用re还是compi ...
- python中调用什么模块的什么函数来实现求实数平方根_python语言基础与应用答案...
python语言基础与应用答案 python3不再区分整数和长整数,统一为()类型. python可以使用(____)函数打开文件,这个函数默认的打开模式为(____). a=[3]alist=[1, ...
- python中callable_Python abc.Callable方法代码示例
本文整理汇总了Python中collections.abc.Callable方法的典型用法代码示例.如果您正苦于以下问题:Python abc.Callable方法的具体用法?Python abc.C ...
- python中的numpy模块
参考 python中的numpy模块 - 云+社区 - 腾讯云 目录 NumPy 教程 学习本教程前你需要了解 NumPy 应用 相关链接 NumPy 安装 1.使用已有的发行版本 2.使用 pip ...
- 介绍Python中的__future__模块
这篇文章主要介绍了介绍Python中的__future__模块,__future__模块使得在Python2.x的版本下能够兼容更多的Python3.x的特性,需要的朋友可以参考下 Python的每个 ...
- python中的logging记录日志_[ Python入门教程 ] Python中日志记录模块logging使用实例...
python中的logging模块用于记录日志.用户可以根据程序实现需要自定义日志输出位置.日志级别以及日志格式. 将日志内容输出到屏幕 一个最简单的logging模块使用样例,直接打印显示日志内容到 ...
- python使用教程cmd啥意思-Python 中的cmd模块学习
Python中的cmd模块类型提供了一个创建命令行解析器的框架.简单的来说,可以继承Cmd来创建命令行界面,然后对所有想处理的命令command执行do_command方法.默认情况下,它使用read ...
- python中的绘图模块turtle的使用
python中的绘图模块turtle的使用(7-20190125) 文章目录: 还是从一个有趣的小应用开始,turtle的骚操作吧 最近小猪配齐比较流行,下面用turtle绘制一个粉红色的小猪猪吧-- ...
- linux系统python截图不显示中文_Linux运维知识之解决linux系统下python中的matplotlib模块内的pyplot输出图片不能显示中文的问题...
本文主要向大家介绍了Linux运维知识之解决linux系统下python中的matplotlib模块内的pyplot输出图片不能显示中文的问题,通过具体的内容向大家展现,希望对大家学习Linux运维知 ...
- Python中的random模块
Python中的random模块用于随机数生成,对几个random模块中的函数进行简单介绍.如下: random.random() 用于生成一个0到1的随机浮点数.如: import random r ...
最新文章
- 实例讲解决策树分类器
- 子元素绝对定位absolute后,自动撑开宽度
- django博客项目8:文章详情页
- 解决ASP.NET AJAX在frame及iframe中跨域访问的问题
- 【SpringBoot】SpringBoot、ThemeLeaf 官方文档地址
- 论发展的十大关系。总结过去,正视未来!!!
- [Java]java反射随笔
- php 数组 定义 遍历,php针对数组的定义、遍历及删除
- windows7企业版 IIS常见问题
- Eureka常用配置
- idea 热部署时 tomcat处 没有update classes and resource 选项
- ElementUI以及uvie的图标使用和设置---SpringCloud Alibaba_若依微服务框架改造_ElementUI+uniapp_uview---工作笔记015
- Centos6.5下通过shell脚本快速安装samba服务器
- CocoaPods 2017最新、最快安装和使用说明
- 推动区块链基础设施建设,先要破解区块链发展“三高”难题
- html5 人物画像,人物头像画不准?掌握这五步,让你把人物头像画准,画像
- 华为人工智能atlasA800-9000物理服务器离线安装及CANN安装和MindSpore安装和Tensorflow安装
- Axure8 全选控制中继器里的checkbox
- 自旋锁为什么不适用于单处理器系统
- 记 PS2020 打开闪退问题