Python拓展17(抽象基类---abc模块)
1、前言
python中并没有提供抽象类与抽象方法,但是提供了内置模块abc(abstract base class)来模拟实现抽象类。
可以通过abc将基类声明为抽象类的方式,然后注册具体类作为这个基类的实现。
2、定义抽象类
首先在abc_base.py中定义一个抽象基类PluginBase,这个基类用于保存和加载数据。
import abc class PluginBase(object): __metaclass__ = abc.ABCMeta @abc.abstractmethod def load(self, input): """Retrieve data from the input source and return an object.""" return @abc.abstractmethod def save(self, output, data): """Save the data object to the output.""" return
通过@abc.abstractmethod将方法声明为抽象方法
3、注册具体类
然后在abc_register.py中定义一个具体的类:
import abc from abc_base import PluginBase class 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)
RegisteredImplementation并没有继承自PluginBase,而是将其注册为PluginBase的一个实现。
运行结果
Subclass: True
Instance: True
4、通过派生实现
也可以在abc_subclass.py中直接继承抽象类:
mport abc from abc_base import PluginBase class 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)
这样做有一个副作用,当查询基类的子类时,会输出所有继承自基类的子类。
import abc from abc_base import PluginBase import abc_subclass import abc_register for sc in PluginBase.__subclasses__(): print sc.__name__
结果:
SubclassImplementation
5、不完整的实现
直接从抽象基类派生子类有一个好处,除非子类完全抽象基类的抽象方法,否则子类不能实例化。
import abc from abc_base import PluginBase class IncompleteImplementation(PluginBase): def save(self, output, data): return output.write(data) if __name__ == '__main__': print 'Subclass:', issubclass(IncompleteImplementation, PluginBase) print 'Instance:', isinstance(IncompleteImplementation(), PluginBase)
6、ABC中的具体方法
尽管具体子类必须实现抽象类中的所有抽象方法,但是,抽象类中也可以包含具体方法。在子类中可以通过super()来调用。
import abc from cStringIO import StringIO class ABCWithConcreteImplementation(object): __metaclass__ = abc.ABCMeta @abc.abstractmethod def 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 response input = StringIO("""line one line two line three """) reader = ConcreteOverride() print reader.retrieve_values(input)
结果
base class reading data subclass sorting data ['line one', 'line three', 'line two']
7、抽象属性
可以通过@abstractproperty定义抽象属性:
import abc class Base(object): __metaclass__ = abc.ABCMeta @abc.abstractproperty def value(self): return 'Should never get here' class Implementation(Base): @property def 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
结果
ERROR: Can't instantiate abstract class Base with abstract methods value Implementation.value: concrete property
8、摘自
https://www.jianshu.com/p/19ed49293168

浙公网安备 33010602011771号