Python中的abc模块

news/2024/12/20 18:38:02/

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各自的区别。


http://www.ppmy.cn/news/880111.html

相关文章

mysql 联合索引 abc_ABC联合索引生效问题(整理笔记!!!)

版权声明:本文为博主原创文章,遵循CC 4.0 by-sa版权协议,转载请附上原文出处链接和本声明。 本文链接:https://blog.csdn.net/qq_42630887/article/details/97113323 对于复合索引:Mysql从左到右的使用索引中的字段,一个查询可以只使用索引中的一部份,但只能是最左侧部分…

Python高级:了解Python ABC(抽象基类)及 应用场景

ABC&#xff0c;Abstract Base Class&#xff08;抽象基类&#xff09;&#xff0c;主要定义了基本类和最基本的抽象方法&#xff0c;可以为子类定义共有的API&#xff0c;不需要具体实现。相当于是Java中的接口或者是抽象类。 抽象基类可以不实现具体的方法&#xff08;当然也…

IP地址ABC类

以下表列出留用的内部寻址地址 A类 10.0.0.0 --10.255.255.255 B类 172.16.0.0--172.31.255.255 C类 192.168.0.0--192.168.255.255 1. A类地址 ⑴ A类地址第1字节为网络地址&#xff0c;其它3个字节为主机地址。另外第1个字节的最高位固定为0。 ⑵ A类地址范围&#xff1a;1.0…

计算机网络中abc类地址,abc类ip地址-abc类ip地址和私有地址范围

1.A类IP地址 一个A类IP地址由1字节的网络地址和3字节主机地址组成,网络地址的最高位必须是“0”,地址范围从到.。可用的A类网络有个,每个网络能容纳1亿多个主机。 2.B类IP地址 一个B类IP地址由2个字节的网络地址和2个字节的主机地址组成,网络地址的最高位必须是“10”,地…

python中sep是什么意思_python中sep是什么意思

全称为Separate意为 分开 隔开 用于print两个元素时自定义间隔符(默认为两个空格) 关键字参数sep是实现分隔符&#xff0c;比如多个参数输出时想要输出中间的分隔字符 print(1, 2, 3, sep ,, end \r\n) print(1, 2, 3, sep , end \r\n) 相关推荐&#xff1a;《python视频教…

maya导入abc动画_完美动力小课堂:abc格式应用--Realflow和Maya互导

熟悉Realflow软件的同学应该都知道,想要在和Maya中互相导入导出,需要安装Realflow官方的接口文件。但是随着软件更新换代的速度,接口文件赶不上软件的更新。那我们该怎么办呢? 今天由完美动力孙老师为大家介绍一个方法,通过abc格式,实现Realflow和Maya的互导。 打开Maya,随便制…

maya导入abc动画_如此导出ABC缓存,扩展秘籍(二)!!!

大家好,又有很长时间没有更新文章了,忙里偷闲,这次打算把上篇文章做一些补充,也是在实际项目中正则运用的一些扩展,如果还没有看上篇文章的话,可以看看如此导出ABC缓存,当真是隐藏秘籍啊!!!(源码+插件),话不多说,开始吧。 这次主要更新扩展了maya导出abc时,无…

Python之abc模块

abc&#xff1a;Abstract Base Classes 作用&#xff1a;在代码中定义和使用抽象基类进行API检查。 1. 为什么使用abc&#xff1f; Abstract base classes由一组接口组成&#xff0c;检查比hasattr()更严格。通过定义一个抽象基类&#xff0c;可以为一组子类定义一个通用的API。…