Python霧裡看花-抽象類ABC (abstract base class)
阿新 • • 發佈:2018-11-12
首先認識模組 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
- 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方法來實現虛擬方法的檢查