XiWind 西風之劍
HomeTechProContactGitHub
  • About
  • Git
    • Windows Terminal、PowerShell 安裝
    • Git 開始使用
    • Branch 入門
    • 合併多個 Commit , 編輯
    • 額外功能
  • deep learning
    • Dilated Convolution
  • Python
    • GIL 【全域直譯器鎖】
    • PyPy 【JIT 編譯器】
    • Decorator 【修飾器】
      • Class Decorators
  • Python library
    • abc 【抽象 Class】
      • ABC, ABCMeta
      • __abstractmethods__, get_cache_token, update_abstractmethods
    • dataclasses 【數據 Class】
      • make_dataclass(), replace(), is_dataclass(), __post_init__
    • enum 【列舉 Class】
      • Flag, auto(), unique, verify()
      • 範例
    • concurrent.futures 【執行緒、程序】
      • Future, Module Functions
    • queue 【佇列、同步】
      • full(), empty(), qsize(), join(), task_done()
    • functools 【可調用物件】
      • ordering、wrapper、partial
      • Overloading
    • heapq 【堆積佇列】
      • heapify(), merge(), nlargest(), nsmallest()
    • time 【時間】
      • time(), monotonic(), perf_counter()...
      • sleep(), 範例...
    • logging 【日誌】
Powered by GitBook
On this page
  • __abstractmethods__
  • get_cache_token()
  • update_abstractmethods()
  • 範例 – 計算面積
  • 範例 – 影像處理
  • 參考資料

Was this helpful?

  1. Python library
  2. abc 【抽象 Class】

__abstractmethods__


是一個維護系統的屬性,包含必須由 abstract base class 的具體子類別實現的抽象方法和屬性的名稱。

當使用 abc module 定義 abstract base class 時,任何用 @abstractmethod 修飾的方法都會加入到 __abstractmethods__ set 中。除非覆寫其所有抽象方法,否則無法實例化從 abstract base class 繼承的類別。

Example: Basic usage

PYTHON
import abc

class ElectronicDevice(abc.ABC):
    @abc.abstractmethod
    def turn_on(self):
        pass

    @abc.abstractmethod
    def turn_off(self):
        pass

    @property
    @abc.abstractmethod
    def is_on(self):
        pass


class Television(ElectronicDevice):
    def __init__(self):
        self._is_on = False

    def turn_on(self):
        if not self._is_on:
            self._is_on = True
            print("Television is now ON.")

    def turn_off(self):
        if self._is_on:
            self._is_on = False
            print("Television is now OFF.")

    @property
    def is_on(self):
        return self._is_on
    
print(ElectronicDevice.__abstractmethods__) # Output: frozenset({'turn_on', 'turn_off', 'is_on'})
print(Television.__abstractmethods__)       # Output: frozenset()

get_cache_token()


提供了一個 token,每次透過 register() 修改ABC時,該 token 都會更改。此 token 對於 caching 和追蹤 ABC registry 的變更很有用。

它返回一個不透明的物件 (意味著用戶無法直接理解或使用其內部結構),用於標記 Virtual subclass cache 的版本。 該物件支援相等性測試,因此可以用來檢查 cache 是否已經更改。

PYTHON
abc.get_cache_token()

每次在調用 register() 時,cache token 都會發生變化。 這意味著當您註冊 Virtual subclass cache 時,cache token 將會更改。

Cache token 是一種版本控制的機制。

它主要用於處理大型 Class 層次結構,並且需要確保正確傳遞 Abstract Class 中的更改的情況。大多數 Python 開發人員可能永遠不需要使用 get_cache_token()。

Example: Basic usage

import abc
from abc import ABC

class MyABC(ABC):
    pass

cache_token = abc.get_cache_token()
print(cache_token)  # Output: 37

# Function to demonstrate cache token usage
def is_abc_up_to_date(cache_token):
    current_token = abc.get_cache_token()
    return  current_token == cache_token

print("ABC registry updated:", not is_abc_up_to_date(cache_token)) # Output: False

@MyABC.register
class MyConcreteClass:
    pass
print("ABC registry updated:", not is_abc_up_to_date(cache_token)) # Output: True

update_abstractmethods()


用於重新計算 Abstract class 的抽象狀態,在建立 Class 後加入或實現 abstract 方法的情況下非常有用。

如果沒有使用 update_abstractmethods(cls),Python 不會自動重新計算的 abstract 方法。

PYTHON
abc.update_abstractmethods(cls)

在 Abstract class 已經定義之後,您不能動態地加入新的 abstract 方法。 僅能使用 update_abstractmethods() 。

update_abstractmethods() 並不常用。用例涉及動態行為,這在傳統的 Python 應用程式中並不常見。它更常見於進行大量 meta-programming 的 rameworks or libraries 中。

頻繁使用此函數會使程式碼更難以理解和維護。通常最好對 class 層次結構有一個清晰、靜態的定義。

Example: Basic usage

PYTHON
from abc import ABC, abstractmethod, update_abstractmethods

class AbstractParent(ABC): 
    @abstractmethod
    def do_something(self): 
        pass


class ChildClass(AbstractParent): 
    pass


try: 
    c = ChildClass()  # ❌❌
except TypeError as e: 
    print(e)  
    
def do_something_implementation(self): 
    print("Doing something!")

# Recompute abstract state
ChildClass.do_something = do_something_implementation
update_abstractmethods(ChildClass)

c = ChildClass()      # ✔️✔️
c.do_something()      # Output:  Doing something!

範例 – 計算面積


PYTHON
from abc import ABC, abstractmethod

class Polygon(ABC):
    def __init__(self, sides):
        super().__init__()
        self.sides = sides

    @abstractmethod
    def area(self):
        """Verification of side length"""
        if not all(i > 0 for i in self.sides):
            raise ValueError("All side lengths must be positive")

class Rectangle(Polygon):
    def __init__(self, sides):
        super().__init__(sides)

    def area(self):
        super().area()
        # Calculate rectangle area
        return self.sides[0] * self.sides[1]

class Triangle(Polygon):
    def __init__(self, sides):
        super().__init__(sides)

    def area(self):
        super().area()
        # Calculate Heron's formula
        s = sum(self.sides) / 2
        return (s * (s - self.sides[0]) * (s - self.sides[1]) * (s - self.sides[2])) ** 0.5

print(Rectangle([5, 10]).area())      # Output: 50
print(Triangle([20, 10, 15]).area())  # Output: 72.618

範例 – 影像處理


PYTHON
from abc import ABC, abstractmethod
from PIL import Image

class ImageProcessor(ABC):
    def __init__(self, image_path):
        super().__init__()
        self.image = Image.open(image_path)

    @abstractmethod
    def process(self):
        if self.image.mode != 'RGB':
            raise ValueError("Image mode must be RGB")

class ImageResizer(ImageProcessor):
    def __init__(self, image_path, size):
        super().__init__(image_path)
        self.size = size

    def process(self):
        super().process() # Resize the image
        return self.image.resize(self.size)

class ImageRotator(ImageProcessor):
    def __init__(self, image_path, angle):
        super().__init__(image_path)
        self.angle = angle

    def process(self):
        super().process() # Rotate the image
        return self.image.rotate(self.angle)

resizer = ImageResizer('image.jpg', (800, 800))
resized_image = resizer.process()
resized_image.save('resized_image.jpg')

rotator = ImageRotator('image.jpg', 90)
rotated_image = rotator.process()
rotated_image.save('rotated_image.jpg')

參考資料


PreviousABC, ABCMetaNextdataclasses 【數據 Class】

Last updated 1 year ago

Was this helpful?

abc — Abstract Base Classes — Python 3.11.4 documentation
PEP 3119 – 引入抽象基類 | peps.python.org
Python 中的抽象基類 (abc) - GeeksforGeeks
Python interfaces: abandon ABC and switch to Protocols | by Oleg Sinavski | Level Up Coding
python抽象類別 abc模組 - 知乎
Page cover image