python抽象基类abc

作者: nummycode | 来源:发表于2016-10-09 18:45 被阅读3071次

    python中并没有提供抽象类与抽象方法,但是提供了内置模块abc(abstract base class)来模拟实现抽象类。

    可以通过abc将基类声明为抽象类的方式,然后注册具体类作为这个基类的实现。

    定义抽象类

    首先在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将方法声明为抽象方法。

    注册具体类

    然后在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
    

    通过派生实现

    也可以在abc_subclass.py中直接继承抽象类:

    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)
    

    这样做有一个副作用,当查询基类的子类时,会输出所有继承自改类的子类。

    import abc
    from abc_base import PluginBase
    import abc_subclass
    import abc_register
    
    for sc in PluginBase.__subclasses__():
        print sc.__name__
    

    输出结果如下:

    SubclassImplementation
    

    不完整的实现

    直接从抽象基类派生子类有一个好处,除非子类完全抽象基类的抽象方法,否则子类不能实例化。

    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)
    

    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)
    print
    

    输出结果如下:

    base class reading data
    subclass sorting data
    ['line one', 'line three', 'line two']
    

    抽象属性

    可以通过@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
    

    相关文章

      网友评论

      本文标题:python抽象基类abc

      本文链接:https://www.haomeiwen.com/subject/nbqmyttx.html