Python雾里看花-抽象类ABC (abstract base class)
程序员文章站
2024-02-17 17:32:22
...
首先认识模块 abc,python中没有提供抽象类与抽象方法,然而提供了内置模块abc来模拟实现抽象类,例如提供泛映射类型的抽象类 abc.MutableMapping
- 继承abc.MutableMapping构造一个泛映射类型(类似python中的dict)
# -*- coding: utf-8 -*-
from collections import abc
class MyDic(abc.MutableMapping):
def __init__(self):
pass
def __setitem__(self, key, value):
print ('key: %s val: %s' % (key, value))
def __delitem__(self, key):
print ('key: %s ' % key)
def __getitem__(self, item):
print ('item: %s ' % str(item))
def __iter__(self):
pass
def __len__(self):
pass
- 当然继承abc.Mapping 也可以,毕竟MutableMapping是其子类
- dict是python中典型的映射类型数据结构,其接口的定义形式也来自abc.Mapping和abc.MutableMapping这俩种抽象类
# -*- coding: utf-8 -*-
from collections import abc
if __name__ == '__main__':
mydic = dict()
print( issubclass(dict, abc.MutableMapping))
print( issubclass(dict, abc.Mapping))
print( isinstance(mydic, abc.MutableMapping))
print( isinstance(mydic, abc.Mapping))
- 运行结果
True
True
True
True
关于abc的通用模块
- abc.ABCMeta 用来生成抽象基础类的元类。由它生成的类可以被直接继承,如下是以注册的方式使用元类。
# -*- coding: utf-8 -*-
from abc import ABCMeta
"""
生成了一个MyABCDict的抽象基础类,然后再将dict注册成它的虚拟子类。
然后通过issubclass或者isinstance都可以判断出dict确实是出于MyABCDict类
不会出现在类的MRO (Method Resolution Order),因而也不能通过super()来调用抽象方法。
没有实现抽象方法时,实例化时候不会报错,只有在调用时候才会报错。
"""
class MyABCDict(metaclass=ABCMeta):
pass
if __name__ == '__main__':
MyABCDict.register(dict)
print( issubclass(dict, MyABCDict))
print( isinstance({}, MyABCDict))
- abc.ABC辅助类,让你可以不用关心元类概念,直接继承它,就有了ABCMeta元类。使用时注意元类冲突
- @abc.abstractmethod 定义抽象方法,除了这个装饰器,其余装饰器都被deprecated了。
继承方式使用元类
- 优点:直接从抽象基类派生子类有一个好处,除非子类实现抽象基类的抽象方法,否则子类不能实例化。
import abc
class PluginBase(metaclass= abc.ABCMeta):
#__metaclass__ = abc.ABCMeta
@abc.abstractmethod
def do_something(self, input):
"""Do Some thing."""
return
class SomePlugin(PluginBase):
def do_something(self, input):
print('do_something')
if __name__ == '__main__':
print ('Subclass:', issubclass(SomePlugin, PluginBase))
print ('Instance:', isinstance(SomePlugin(), PluginBase))
- 可以通过 subclasshook方法来实现虚拟方法的检查