python 抽象類分析

最近在看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

相關文章
相關標籤/搜索