Python ABC(抽象基类)

轉自:https://blog.csdn.net/qijiqiguai/article/details/77269839

 

ABC(Abstract Base Class抽象基类)主要定义了不需要具体实现之基本类和抽象方法,可以为子类定义共有的API,相当于是Java中的接口或者是抽象类。

    Python 对于ABC的支持模块是abc模块,定义了一个特殊的metaclass:ABCMeta 还有一些装饰器:@abstractmethod@abstarctproperty 。abc.ABCMeta 用于在Python程序中创建抽象基类,而抽象基类如果想要声明抽象方法,可以使用 @abstractmethod ,如果想声明抽象属性,可以使用 @abstractproperty

    为了解决Python2&3的兼容问题,需要引入six模块,该模块中有一个针对类的装饰器 @six.add_metaclass(MetaClass) 可以为两个版本的Python类方便地添加metaclass

通用做法:以裝飾器手法修飾類別

@six.add_metaclass(MetaClass) 的作用是在不同版本的Python之间提供一个优雅的声明类的metaclass的手段,事实上不用它也可以,只是使用了它代码更为整洁

import six

import abc

@six.add_metaclass(abc.ABCMeta)

class MyClass(object):

       pass

在Python 3 等价于

import six

import abc

class MyClass(object, metaclass = ABCMeta):

        pass

在Python 2.x (x >= 6)中等价于

import abc

class MyClass(object):

        __metaclass__ = ABCMeta

        pass

不建議採用此法:在類別中以方法作定義

或者直接调用装饰器,这里也能看出来装饰器就是个方法包装而已

import six

import abc

class MyClass(object):

        pass

MyClass  = six.add_metaclass(ABCMeta)(MyClass)

 

示例:

import abc

import six

 

@six.add_metaclass(abc.ABCMeta)

class BaseClass(object):

    @abc.abstractmethod

    def func_a(self, data):

        """

        an abstract method need to be implemented

        """

 

    @abc.abstractmethod

    def func_b(self, data):

        """

        another abstract method need to be implemented

        """

 

class SubclassImpl(BaseClass):

    def func_a(self, data):

        print("Overriding func_a, " + str(data))

 

    @staticmethod

    def func_c(self, data):

        print(type(self) + str(data))

 

class RegisteredImpl(object):

    @staticmethod

    def func_d(data):

        print("Method in third-party class, " + str(data))

 

BaseClass.register(RegisteredImpl)   #BaseClass具有RegisteredImpl功能,此也是其下子類別

 

if __name__ == '__main__':

    for subclass in BaseClass.__subclasses__():   #由內定__subclasses__()方法查看含有那些子類別

        print("subclass of BaseClass: " + subclass.__name__#只會顯示繼承体系下之子類別,register()方式不會顯示

    print("subclass do not contains RegisteredImpl")

    print("-----------------------------------------------")

 

    print("RegisteredImpl is subclass: " + str(issubclass(RegisteredImpl, BaseClass)))

    print("RegisteredImpl object  is instance: " + str(isinstance(RegisteredImpl(), BaseClass)))

    print("SubclassImpl is subclass: " + str(issubclass(SubclassImpl, BaseClass)))

 

    print("-----------------------------------------------")

    obj1 = RegisteredImpl()

    obj1.func_d("RegisteredImpl new object OK!")

    print("-----------------------------------------------")

    obj2 = SubclassImpl()  #由于没有实例化所有的方法,所以这里会报错 Can't instantiate abstract class SubclassImpl with abstract methods func_b

    obj2.func_a("It's right!")

结果如下:

subclass of BaseClass: SubclassImpl

subclass do not contains RegisteredImpl

-----------------------------------------------

RegisteredImpl is subclass: True

RegisteredImpl object  is instance: True

SubclassImpl is subclass: True

-----------------------------------------------

Method in third-party class, RegisteredImpl new object OK!

-----------------------------------------------

Traceback (most recent call last):

  File "/Users/wangqi/Git/Python/scrapy_crawler_learn/test/ABCTest.py", line 51, in

    obj2 = SubclassImpl()  #由于没有实例化所有的方法,所以这里会报错 Can't instantiate abstract class SubclassImpl with abstract methods func_b

TypeError: Can't instantiate abstract class SubclassImpl with abstract methods func_b

補充:參考 https://blog.csdn.net/ChangerJJLee/article/details/82355872

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是其子类,如下圖:

https://img-blog.csdn.net/20180903212330758?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L0NoYW5nZXJKSkxlZQ==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70

  • 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的通用模块

---------------------

作者:AngelovLee

来源:CSDN

原文:

版权声明:本文为博主原创文章,转载请附上博文链接!

你可能感兴趣的:(Python)