欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Python雾里看花-抽象类ABC (abstract base class)

程序员文章站 2024-02-17 17:32:22
...

首先认识模块 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 也可以,毕竟MutableMapping是其子类

Python雾里看花-抽象类ABC (abstract base class)

  • 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方法来实现虚拟方法的检查