
__abstractmethods__
是一個維護系統的屬性,包含必須由 abstract base class 的具體子類別實現的抽象方法和屬性的名稱。
當使用 abc
module 定義 abstract base class 時,任何用 @abstractmethod
修飾的方法都會加入到 __abstractmethods__
set 中。除非覆寫其所有抽象方法,否則無法實例化從 abstract base class 繼承的類別。
Example: Basic usage
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 是否已經更改。
abc.get_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 方法。
abc.update_abstractmethods(cls)
頻繁使用此函數會使程式碼更難以理解和維護。通常最好對 class 層次結構有一個清晰、靜態的定義。
Example: Basic usage
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!
範例 – 計算面積
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
範例 – 影像處理
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')
參考資料
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
Last updated
Was this helpful?