最近在看bottle.py源碼,裏面自定了多個類字典的類。這些類的定義繼承了collections中多個抽象類。好比MutableMapping。java
一、在講抽象類以前,先說下抽象方法的實現。python
抽象方法是基類中定義的方法,但卻沒有任何實現。在java中,能夠把方法申明成一個接口。而在python中實現一個抽象方法的簡單的方法是:api
class Sheep(object): def get_size(self): raise NotImplementedError
任何從Sheep繼承下來的子類必須實現get_size方法。不然就會產生一個錯誤。但這種實現方法有個缺點。定義的子類只有調用那個方法時纔會拋錯。這裏有個簡單方法能夠在類被實例化後觸發它。使用python提供的abc模塊。安全
import abc class Sheep(object): __metaclass__ = abc.ABCMeta @abc.absractmethod def get_size(self): return
這裏實例化Sheep類或任意從其繼承的子類(未實現get_size)時候都會拋出異常。app
所以,經過定義抽象類,能夠定義子類的共同method(強制其實現)。
this
二、抽象類的定義。
spa
python中,抽象類經過abc模塊實現。code
import abcclass 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
具體化抽象類,能夠有兩種方式,一種經過註冊(register),另一種經過繼承。
繼承
註冊方式:
接口
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)
繼承方式:
import 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)
執行發現,註冊方式和繼承方式不一樣在於,註冊方式,當沒有實現抽象方法時,實例化時候不會報錯,但調用時候會報錯。
三、抽象類中除了抽象方法外,也能夠實現抽象屬性(@abstraproperty)。
import abcclass 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.valueexcept Exception, err: print 'ERROR:', str(err)i = Implementation()print 'Implementation.value:', i.value
另外子類中抽象屬性實現必須與抽象屬性定義一致。
import abc class Base(object): __metaclass__ = abc.ABCMeta def value_getter(self): return 'Should never see this' def value_setter(self, newvalue): return value = abc.abstractproperty(value_getter, value_setter) class PartialImplementation(Base): @abc.abstractproperty def value(self): return 'Read-only'class Implementation(Base): _value = 'Default value' def value_getter(self): return self._value def value_setter(self, newvalue): self._value = newvalue value = property(value_getter, value_setter)try: b = Base() print 'Base.value:', b.valueexcept Exception, err: print 'ERROR:', str(err)try: p = PartialImplementation() print 'PartialImplementation.value:', p.valueexcept Exception, err: print 'ERROR:', str(err)i = Implementation() print 'Implementation.value:', i.valuei.value = 'New value'print 'Changed value:', i.value
四、collections
collections模塊定義了幾個抽象類。
General container classes:
Container
Sized
Iterator and Sequence classes:
Iterable
Iterator
Sequence
MutableSequence
Unique values:
Hashable
Set
MutableSet
Mappings:
Mapping
MutableMapping
MappingView
KeysView
ItemsView
ValuesView
Miscelaneous:
Callable
python的內置類型在import collections時,會自動被註冊到這些類中。所以你能夠安全的使用isinstance或issubclass來保證執行某些api