
✍️ 常見裝飾器應用範例
計時器
- 計算函數運行的時間
- 運算時間對於機器學習模型來說非常重要,這會影響到模型訓練與部署推論的資源需求
import time
def timer_decorator(func):
def wrapper(*args, **kwargs):
start_time = time.time() # 記錄執行開始時間
result = func(*args, **kwargs)
end_time = time.time() # 記錄執行結束時間
print(f"{func.__name__} 執行時間:{end_time - start_time:.4f} 秒")
return result
return wrapper
@timer_decorator
def calculate_sum(n):
return sum(range(n))
result = calculate_sum(1000000)
print(f"結果為:{result}")
# 輸出
calculate_sum 執行時間:0.0253 秒
結果為:499999500000
日誌紀錄器
- 紀錄函數執行過程的資訊
- Log紀錄在程式開發過程中很重要,有利於測試以及Debug
def logger_decorator(func):
def wrapper(*args, **kwargs):
print(f"執行 {func.__name__},參數為 args: {args}, kwargs: {kwargs}")
result = func(*args, **kwargs)
print(f"{func.__name__} 執行結束,結果為:{result}")
return result
return wrapper
@logger_decorator
def multiply(a, b):
return a * b
result = multiply(4, 5)
# 輸出
執行 multiply,參數為 args: (4, 5), kwargs: {}
multiply 執行結束,結果為:20
🗂️ 標準裝飾器
Python 提供了一些內建的 標準裝飾器 (Standard Decorators),主要用於支援物件導向程式設計 (Object-Oriented Programming, OOP) 的特性,以及對函數的行為進行修改。常見的標準裝飾器有:
@staticmethod@classmethod@property
@staticmethod:定義靜態方法
- 功能:
- 將類別中的方法定義為靜態方法,靜態方法不會接收 實例物件 (self) 或 類別物件 (cls) 作為默認參數。
- 它是一個與類別相關的普通函數,無需存取類別或實例的任何屬性或方法。
- 用途:
- 用於封裝一些獨立於實例或類別的邏輯。
- 節省資源,消除調用 self 和 cls 的需求。
class MathUtility:
@staticmethod
def add(a, b):
"""計算兩數的加總"""
return a + b
@staticmethod
def multiply(a, b):
"""計算兩數的乘積"""
return a * b
# 不需要創建實例,可直接通過類別名調用
print(MathUtility.add(3, 5)) # 8
print(MathUtility.multiply(4, 6)) # 24
@classmethod:定義類別方法
- 功能:
- 將方法定義為 類別方法,類別方法會接收 類別本身 (cls) 作為第一個參數,而不是實例對象 (self)。
- 用途:
- 可以調用或修改類別層級的屬性。
- 經常用於創建類別的其他構造方法(例如工廠方法模式)。
class Person:
count = 0 # 類別屬性,記錄已創建的實例數量
def __init__(self, name):
self.name = name
Person.count += 1
@classmethod
def total_instances(cls):
"""返回已創建的實例數量"""
return cls.count
# 創建實例
p1 = Person("Alice")
p2 = Person("Bob")
# 使用類別方法
print(Person.total_instances()) # 2
@property:定義屬性方法
- 功能:
- 將方法轉換為類似屬性的行為,允許通過點語法訪問而非直接調用。
- 屬性方法能確保屬性的封裝性,並能在屬性訪問時動態地進行邏輯處理。
- 用途:
- 實現 getter 和 setter,用於保護屬性並提供控制邏輯。
- 提升封裝性,避免直接操作內部屬性。
class Circle:
def __init__(self, radius):
self._radius = radius # 私有屬性
@property
def radius(self):
"""獲取半徑"""
return self._radius
@radius.setter
def radius(self, value):
"""設置半徑,並確保其大於零"""
if value <= 0:
raise ValueError("半徑必須大於 0")
self._radius = value
@property
def area(self):
"""計算圓的面積"""
return 3.14 * (self._radius ** 2)
# 使用屬性方法
circle = Circle(5)
print(circle.radius) # 5
circle.radius = 10
print(circle.area) # 314.0
比較

綜合範例
class BankAccount:
bank_name = "Python Bank" # 類別屬性
def __init__(self, owner, balance=0.0):
self.owner = owner
self._balance = balance # 私有屬性
@staticmethod
def interest_rate():
"""靜態方法:定義固定的利率"""
return 0.05
@classmethod
def change_bank(cls, new_name):
"""類別方法:修改銀行名稱"""
cls.bank_name = new_name
@property
def balance(self):
"""屬性方法:獲取帳戶餘額"""
return self._balance
@balance.setter
def balance(self, amount):
"""屬性方法:設置帳戶餘額,僅允許非負數"""
if amount < 0:
raise ValueError("餘額不能為負")
self._balance = amount
# 使用靜態方法
print(BankAccount.interest_rate()) # 0.05
# 使用類別方法
print(BankAccount.bank_name) # Python Bank
BankAccount.change_bank("CodeBank")
print(BankAccount.bank_name) # CodeBank
# 使用屬性方法
account = BankAccount("Alice", 1000)
print(account.balance) # 1000
account.balance = 1500
print(account.balance) # 1500
# 輸出
0.05
Python Bank
CodeBank
1000
1500


