Python抽象基類abc

秀兒y發表於2023-04-07
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'

相關文章