CodeGym /課程 /Python SELF TW /裝飾器的威力

裝飾器的威力

Python SELF TW
等級 14 , 課堂 2
開放

6.1 類別方法的裝飾器

裝飾器也可以用於類別方法。重要的是要記住,對於類別方法,必須正確地傳遞參數 selfcls

我們還沒有深入學習類別的細節,但我希望你知道裝飾器是有這樣的功能的。


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))
留言
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION