Python之abc模块

news/2024/12/20 23:56:21/

abc:Abstract Base Classes

作用:在代码中定义和使用抽象基类进行API检查。

1. 为什么使用abc?

Abstract base classes由一组接口组成,检查比hasattr()更严格。通过定义一个抽象基类,可以为一组子类定义一个通用的API。这对于第三方为应用提供插件等非常有用,另外当您在一个大型的团队中工作或在一个大型的代码库中,同时将所有的类放在您的头脑中是困难或不可能的时,它也可以帮助您。

2. abc怎么工作

abc通过把基类中的方法标记为抽象方法,并且注册具体类为基类的实现的方式工作。

定义基类: abc_base.py

import abcclass PluginBase(object):__metaclass__ = abc.ABCMeta@abc.abstractmethoddef load(self, input):"""Retrieve data from the input source and return an object."""return@abc.abstractmethoddef save(self, output, data):"""Save the data object to the output."""return

有两种方法表明一个具体类实现了一个抽象类

a) 第一种方法:通过使用abc注册,这种方法下RegisteredImplementation并不是由PluginBase派生,而是通过注册方式.

abc_register.py

import abc
from abc_base import PluginBaseclass RegisteredImplementation(object):def load(self, input):return input.read()def save(self, output, data):return output.write(data)PluginBase.register(RegisteredImplementation)if __name__ == '__main__':print 'Subclass:', issubclass(RegisteredImplementation, PluginBase)print 'Instance:', isinstance(RegisteredImplementation(), PluginBase)

output:

Subclass: True
Instance: True

b) 第一种方法:通过实现PluginBaseAPI,是派生.

abc_subclass.py

import abc
from abc_base import PluginBaseclass SubclassImplementation(PluginBase):def load(self, input):return input.read()def save(self, output, data):return output.write(data)if __name__ == '__main__':print 'Subclass:', issubclass(SubclassImplementation, PluginBase)print 'Instance:', isinstance(SubclassImplementation(), PluginBase)

output:

Subclass: True
Instance: True

两种方式的不同:

  1. SubclassImplementationPluginBase.__subclasses__()中,而RegisteredImplementation不在.
  2. SubclassImplementation必须实现PluginBase中的所有抽象方法,否则会在运行时报错;而RegisteredImplement不需要.

3. 抽象方法的实现

在抽象类中抽象方法也可以提供通用的逻辑实现,这样具体类中就可以通过调用super()重用抽象方法的实现.

import abc
from cStringIO import StringIOclass ABCWithConcreteImplementation(object):__metaclass__ = abc.ABCMeta@abc.abstractmethoddef retrieve_values(self, input):print 'base class reading data'return input.read()class ConcreteOverride(ABCWithConcreteImplementation):def retrieve_values(self, input):base_data = super(ConcreteOverride, self).retrieve_values(input)print 'subclass sorting data'response = sorted(base_data.splitlines())return responseinput = StringIO("""line one
line two
line three
""")reader = ConcreteOverride()
print reader.retrieve_values(input)
print

output:

base class reading data
subclass sorting data
['line one', 'line three', 'line two']

4. 抽象特性(Abstract Properties)

如果你的API规范中还包括属性,那么你可以使用@abstractproperty来定义.

import abcclass Base(object):__metaclass__ = abc.ABCMeta@abc.abstractpropertydef value(self):return 'Should never get here'class Implementation(Base):@propertydef value(self):return 'concrete property'try:b = Base()print 'Base.value:', b.value
except Exception, err:print 'ERROR:', str(err)i = Implementation()
print 'Implementation.value:', i.value

因为Base只有property valuegetter方法的抽象版本,所有它不能被实例化.

output:

ERROR: Can't instantiate abstract class Base with abstract methods value
Implementation.value: concrete property

定义抽象的读写特性

import abcclass Base(object):__metaclass__ = abc.ABCMetadef value_getter(self):return 'Should never see this'def value_setter(self, newvalue):returnvalue = abc.abstractproperty(value_getter, value_setter)class PartialImplementation(Base):@abc.abstractpropertydef value(self):return 'Read-only'class Implementation(Base):_value = 'Default value'def value_getter(self):return self._valuedef value_setter(self, newvalue):self._value = newvalue#定义具体类的property时必须与抽象类的abstract property相同。如果只覆盖其中一个将不会工作。value = property(value_getter, value_setter)try:b = Base()print 'Base.value:', b.value
except Exception, err:print 'ERROR:', str(err)try:p = PartialImplementation()print 'PartialImplementation.value:', p.value
except Exception, err:print 'ERROR:', str(err)i = Implementation()
print 'Implementation.value:', i.valuei.value = 'New value'
print 'Changed value:', i.value

output:

ERROR: Can't instantiate abstract class Base with abstract methods value
ERROR: Can't instantiate abstract class PartialImplementation with abstract methods value
Implementation.value: Default value
Changed value: New value

使用装饰器来实现读写的抽象特性,读和写的方法名应该相同

import abcclass Base(object):__metaclass__ = abc.ABCMeta@abc.abstractpropertydef value(self):return 'Should never see this'@value.setterdef value(self, newvalue):returnclass Implementation(Base):_value = 'Default value'@propertydef value(self):return self._value@value.setterdef value(self, newvalue):self._value = newvaluei = Implementation()
print 'Implementation.value:', i.valuei.value = 'New value'
print 'Changed value:', i.value

output:

Implementation.value: Default value
Changed value: New value

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

相关文章

maya怎么导出abc格式_maya导入abc文件到UE4

由于使用的maya自动绑定QuickRigCharacter,FBX格式导入不了。 然后我就想着abc缓存是否能导入呢?可能这种想法注定是个悲剧。。 于是悲剧开始了~ 真的就像官方文档上说的一样是个实验功能,不要用来做项目了。 静态物体可以选面给材质,注意是选面给材质,然后导入。 但是带缓…

计算机ABC分类法的步骤,ABC分类法的具体步骤

ABC分类法的核心思想是在决定一个事物的众多因素中分清主次,识别出少数的但对事物起决定作用的关键因素和多数的但对事物影响较少的次要因素。现在,学习啦小编来告诉你ABC分类法的具体步骤和基本程序。 ABC分类法的具体步骤 1、收集数据 按分析对象和分析内容,收集有关数据。…

计算机网络的abc类地址,abc类私有ip地址范围

网络IP地址“主要”分为ABC三类,以下是覆盖范围: A类:0.0.0.0 - 127.255.255.255,标谁的子网掩码是255.0.0.0(按子网掩码的另一种标注方法是/8,就是将子网掩码换算成二进制后,从左数起8个1) B类:128.0.0.0 - 191.255.255.255,标谁的子网掩码是255.255.0.0(按子网掩码的…

ABC与库存周转率

ABC与库存周转率 https://blog.csdn.net/chbvb4302/article/details/5731209 ABC分类管理 将库存物品按品种和占用资金的多少分为特别重要的库存(A类);一般的库存(B类);不重要的库存(C类&#…

小经验:sympy.abc最好指定导入,不要全部导入

导入sympy.abc时,尽量明确要使用的符号(一般是拉丁字母和希腊字母),因为如果再sympy之后再导入sympy.abc,则sympy模块下定义的一些符号(例如C , O , S , I , …

Python中的ABC(抽象基类)

毕设老师给的代码里有一行__metaclass__ABCmeta 搜了搜网上关于ABC的资料,大多是英文链接,就自己Google翻译了一下。 abc–Abstract Base Classes(抽象基类) 目的:在代码中定义和使用抽象基类进行API检查。 为何使用抽象基类&am…

Python ABC(抽象基类)

轉自:https://blog.csdn.net/qijiqiguai/article/details/77269839 ABC(Abstract Base Class抽象基类)主要定义了不需要具体实现之基本类和抽象方法,可以为子类定义共有的API,相当于是Java中的接口或者是抽象类。 Pyth…

Python抽象类(ABC)浅析

今天在看apscheduler源代码中,看到abc.py这个文件,出于好奇,深入看了一下。 abc的缩写是Abstract Base Classes,翻译就是抽象基类。详细链接可以查看此处 可以看出这个是类是2007年,由Python创始人Guido van Rossum和…