6.1 類別方法的裝飾器
裝飾器也可以用於類別方法。重要的是要記住,對於類別方法,必須正確地傳遞參數 self 或 cls。
我們還沒有深入學習類別的細節,但我希望你知道裝飾器是有這樣的功能的。
def log_method_call(func):
def wrapper(self, *args, **kwargs):
print(f"調用方法 {func.__name__}")
return func(self, *args, **kwargs)
return wrapper
class MyClass:
@log_method_call
def say_hello(self):
print("Hello from MyClass!")
obj = MyClass()
obj.say_hello()
說明
裝飾器 (log_method_call): 這個裝飾器接受一個方法 func,並返回一個新的函數 wrapper,這個函數在調用方法前輸出一條信息。
被裝飾器裝飾的類別方法 (say_hello): 方法 say_hello 被裝飾器 log_method_call 包裝,這增加了額外的行為在調用時。
輸出:
調用方法 say_hello
Hello from MyClass!
6.2 多個裝飾器
你可以對一個函數使用多個裝飾器,將它們層層覆蓋。裝飾器的應用順序與其聲明順序相反。
def decorator1(func):
def wrapper():
print("裝飾器 1")
func()
return wrapper
def decorator2(func):
def wrapper():
print("裝飾器 2")
func()
return wrapper
@decorator1
@decorator2
def say_hello():
print("Hello!")
say_hello()
說明
裝飾器 (decorator1 和 decorator2): 這些裝飾器 在調用函數 func 前增加了自己的信息。
具有裝飾器的函數 (say_hello): 函數 say_hello 被兩個裝飾器包裝。首先應用 decorator2,然後是 decorator1。
輸出:
# 裝飾器 1
# 裝飾器 2
Hello!
6.3 內建裝飾器
Python 提供了一些內建的裝飾器,用於標準任務,如靜態方法、類方法和屬性。
@staticmethod
裝飾器 @staticmethod 用於創建靜態方法,這不需要類的實例來調用。
class MyClass:
@staticmethod
def static_method():
print("這是靜態方法。")
MyClass.static_method()
@classmethod
裝飾器 @classmethod 用於創建類方法, 它接收類(而不是實例)作為第一個參數。
class MyClass:
@classmethod
def class_method(cls):
print(f"這是類方法 {cls.__name__}.")
MyClass.class_method()
@property
裝飾器 @property 用於創建 getter, setter 和 deleter 用於屬性。
class MyClass:
def __init__(self, value):
self.hidden_value = value
@property
def value(self):
return self.hidden_value
@value.setter
def value(self, new_value):
self.hidden_value = new_value
obj = MyClass(10)
print(obj.value) # 輸出: 10
obj.value = 20
print(obj.value) # 輸出: 20
這些是內建裝飾器,它們的正確運行由 Python 解釋器本身來保證。
6.4 裝飾器的使用範例
日誌記錄
裝飾器可以用於記錄函數和方法的調用。
def log_call(func):
def wrapper(*args, **kwargs):
print(f"調用函數 {func.__name__} 與參數 {args} 和 {kwargs}")
return func(*args, **kwargs)
return wrapper
@log_call
def add(x, y):
return x + y
print(add(2, 3))
訪問控制
裝飾器可以用於控制對函數和方法的訪問。
def require_authentication(func):
def wrapper(*args, **kwargs):
if not args[0].is_authenticated:
raise PermissionError("用戶未認證。")
return func(*args, **kwargs)
return wrapper
class User:
def __init__(self, is_authenticated):
self.is_authenticated = is_authenticated
@require_authentication
def view_profile(self):
print("用戶資料")
user = User(is_authenticated=True)
user.view_profile() # 成功調用
user2 = User(is_authenticated=False)
user2.view_profile() # PermissionError: 用戶未認證。
緩存
裝飾器可以用於緩存函數的結果。
def cache(func):
cached_results = {}
def wrapper(*args):
if args in cached_results:
return cached_results[args]
result = func(*args)
cached_results[args] = result
return result
return wrapper
@cache
def fib(n):
if n < 2:
return n
return fib(n - 1) + fib(n - 2)
print(fib(35))
GO TO FULL VERSION