Loading

Python抽象基类abc

ABC类全称是Abstract Base Classes
  • 抽象基类可以通过ABC派生来简单创建
  • 抽象基类的特点:
    • 基类不应允许初始化
    • 接口方法未实现时报告相关错误
  • 可以把抽象基类想象成建筑的设计图纸,然后子类按图施工
  • abc模块提供了一个元类ABCMeta可定义抽象类
  • 还有一个工具类ABC 可有以继承的方式定义抽象基类
# -*- coding: utf-8 -*-
# @Time:     2023/4/7 14:12     
# @Author:   LiQi
# @Describe:

from abc import ABC


# 继承的方式定义抽象基类
class TestClass(ABC):
    ...

from abc import ABCMeta

# 元类指定的方式定义抽象基类
class TestClass(metaclass=ABCMeta):
    ...
@abstractmethod装饰器
  • 所在的类继承ABC或者声明元类ABCMeta
  • 需要抽象的实例方法添加装饰器 @abstractmethod
  • 使用抽象类, 必须继承该类并实现该类的所有抽象方法
写一个抽象基类,声明抽象方法
# -*- coding: utf-8 -*-
# @Time:     2023/4/7 14:12     
# @Author:   LiQi
# @Describe:

import abc

# 创建数据抽象基类
from abc import ABC
class BasicsCreateData(metaclass=abc.ABCMeta):

    def base_docs(self):
        print('没有声明抽象方法')

    # 声明抽象方法-查询数据
    @abc.abstractmethod
    def get_data(self):
        ...

    # 声明抽象方法-放入数据
    @abc.abstractmethod
    def put_data(self, data):
        ...

    # 声明抽象方法-删除数据
    @abc.abstractmethod
    def del_data(self):
        ...

    # 声明抽象方法-修改数据
    @abc.abstractmethod
    def set_data(self, data):
        ...
抽象未实现示例

image

正确继承抽象类使用示例
# 继承抽象基类-实现所有的abstractmethod抽象方法
# 基类的base_docs没有声明抽象方法,子类可有无需实现
class CreateData(BasicsCreateData):
    def __init__(self):
        self.data_list = []

    def get_data(self):
        return self.data_list

    def set_data(self, data: list):
        self.data_list.extend(data)
        return self.data_list

    def del_data(self):
        self.data_list.clear()

    def put_data(self, data):
        self.data_list.append(data)


if __name__ == '__main__':
    __data = CreateData()
    __data.put_data('test')
    __data.get_data()
    __data.del_data()
    __data.set_data(['1', '2', '3'])
    __data.get_data()

abstractmethod内部实现
def abstractmethod(funcobj):
    """A decorator indicating abstract methods.

    Requires that the metaclass is ABCMeta or derived from it.  A
    class that has a metaclass derived from ABCMeta cannot be
    instantiated unless all of its abstract methods are overridden.
    The abstract methods can be called using any of the normal
    'super' call mechanisms.  abstractmethod() may be used to declare
    abstract methods for properties and descriptors.

    Usage:

        class C(metaclass=ABCMeta):
            @abstractmethod
            def my_abstract_method(self, ...):
                ...
    """
    funcobj.__isabstractmethod__ = True
    return funcobj

  • 装饰器的作用设置funcobj相当于抽象基类的__isabstractmethod__为True
  • 子类在实例的时候会调用 instancecheck 魔法方法检查抽象方法的实现
@abstractstaticmethod装饰器
  • abstractstaticmethod继承staticmethod
  • 相当于是声明静态的抽象方法
@abstractclassmethod装饰器
  • abstractclassmethod继承classmethod
  • 相当于是声明类抽象方法
虚拟子类

为了程序的完整性,有时候我们需要让一个类成为另一个类的子类,但是我们不希望这个继承的操作让我们不得不在挂载的子类上实现那些必须实现的父类抽象函数
Python中提供了一种机制,可以让一个类无条件地挂载到一个抽象类上从而成为它的一个虚拟子类,注册之后不会从父类继承任何方法或属性,所以叫做虚拟子类

@BasicsCreateData.register
class CreateData():
    ...
    
    
# 或者
BasicsCreateData.register(CreateData)

由于虚拟子类不会继承父类任何方法属性,没有get到使用虚拟子类的意义,查阅相关文档,通过注册增加虚拟子类是抽象基类动态性的体现,也是符合Python风格的方式,理解为是一种风格约束或者说父类提供给子类所需的实现标注,像类型标注的name:AnyStr = 'l'

posted @ 2023-04-07 15:54  木子七  阅读(252)  评论(0编辑  收藏  举报