python中并没有提供抽象类与抽象方法,但是提供了内置模块abc(abstract base class)来模拟实现抽象类。

ABC,Abstract Base Class(抽象基类),主要定义了基本类和最基本的抽象方法,可以为子类定义共有的API,不需要具体实现。相当于是Java中的接口或者是抽象类。

Python 对于ABC的支持模块是abc模块,定义了一个特殊的metaclass:ABCMeta 还有一些装饰器:@abstractmethod 和 @abstarctproperty 。

abc.ABCMeta 用于在Python程序中创建抽象基类。如果抽象基类如果想要声明“抽象方法”,可以使用 @abstractmethod;如果想声明“抽象属性”,可以使用 @abstractproperty 。

抽象基类

抽象基类可以不实现具体的方法(当然也可以实现,只不过子类如果想调用抽象基类中定义的方法需要使用super())而是将其留给派生类实现。抽象基类提供了逻辑和实现解耦的能力,即在不同的模块中通过抽象基类来调用,可以用最精简的方式展示出代码之间的逻辑关系,让模块之间的依赖清晰简单。同时,一个抽象类可以有多个实现,让系统的运转更加灵活。而针对抽象类的编程,让每个人可以关注当前抽象类,只关注其方法和描述,而不需要考虑过多的其他逻辑,这对协同开发有很大意义。极简版的抽象类实现,也让代码可读性更高。

抽象基类的使用:

1:直接继承

直接继承抽象基类的子类就没有这么灵活,抽象基类中可以声明”抽象方法“和“抽象属性”,只有完全覆写(实现)了抽象基类中的“抽象”内容后,才能被实例化,而虚拟子类则不受此影响。

2:虚拟子类

将其他的类”注册“到抽象基类下当虚拟子类(调用register方法),虚拟子类的好处是你实现的第三方子类不需要直接继承自基类,可以实现抽象基类中的部分API接口,也可以根本不实现,但是issubclass(), issubinstance()进行判断时仍然返回真值。

抽象基本类的几大特点:

1. 要定义但是并不完整的实现所有方法

2. 基本的意思是作为父类

3. 父类需要明确表示出那些方法的特征,这样在写子类时更加简单明白

用抽象基本类的地方:

1. 用作父类

2. 用作检验实例类型

3. 用作抛出异常说明

abc模块中的类和函数

1. abc.ABCMeta:用来生成抽象基础类的元类。由它生成的类可以被直接继承。

from abc importABCMetaclass MyABC: #1. 首先生成了一个MyABC的抽象基础类

__metaclass__ = ABCMeta #使用了__metaclass__这个魔法方法就意味着就会用__metaclass__指定的元类来创建类了。

MyABC.register(tuple)#2. 然后再将tuple变成它的虚拟子类

assertissubclass(tuple, MyABC)assert isinstance((), MyABC) #3. 再通过issubclass或isinstance都可以判断出tuple是不是出于MyABC类。

也可以通过复写__subclasshook__(subclass)来实现相同功能,它必须是classmethod


classFoo(object):def __getitem__(self, index):
...def __len__(self):
...defget_iterator(self):returniter(self)classMyIterable:__metaclass__ =ABCMeta
@abstractmethoddef __iter__(self):whileFalse:yieldNonedefget_iterator(self):return self.__iter__()
@classmethoddef __subclasshook__(cls, C):if cls isMyIterable:if any("__iter__" in B.__dict__ for B in C.__mro__):returnTruereturnNotImplemented
MyIterable.register(Foo)
View Code
2. abc.abstractmethod(function):表明抽象方法的生成器
classC:__metaclass__ =ABCMeta
@abstractmethoddefmy_abstract_method(self, ...):
...
3. abc.abstractproperty([fget[,fset[,fdel[,doc]]]]): 表明一个抽象属性
classC:__metaclass__ =ABCMeta
@abstractpropertydefmy_abstract_property(self):
...
上例只是只读属性,如果是读写属性,可以如下:
classC:__metaclass__ =ABCMetadefgetx(self): ...defsetx(self, value): ...
x= abstractproperty(getx, setx)
定义抽象类
importabcclass PluginBase(object): #定义一个抽象基类PluginBase,这个基类用于保存和加载数据。
__metaclass__ =abc.ABCMeta
@abc.abstractmethoddefload(self, input):"""Retrieve data from the input source and return an object."""
return@abc.abstractmethoddefsave(self, output, data):"""Save the data object to the output."""
return