在 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')