自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

Python 如何在裝飾器中使用其他函數(shù)?

開發(fā) 前端
在裝飾器中使用其他函數(shù)是一種常見的需求,可以幫助你將復雜的功能分解成更小、更易于管理的部分。

前言

在裝飾器中使用其他函數(shù)是一種常見的需求,可以幫助你將復雜的功能分解成更小、更易于管理的部分。

使用輔助函數(shù)進行日志記錄

假設(shè)你有一個裝飾器,用于在函數(shù)調(diào)用前后記錄日志。你可以將日志記錄的功能提取到一個單獨的輔助函數(shù)中。

import logging
# 配置日志記錄
logging.basicConfig(level=logging.INFO)
def log_message(message):
    logging.info(message)
def log_function_call(func):
    def wrapper(*args, **kwargs):
        log_message(f"Calling {func.__name__} with args={args} kwargs={kwargs}")
        result = func(*args, **kwargs)
        log_message(f"{func.__name__} returned {result}")
        return result
    return wrapper
@log_function_call
def add(a, b):
    return a + b
add(3, 5)

使用輔助函數(shù)進行輸入驗證

假設(shè)你有一個裝飾器,用于驗證函數(shù)的輸入?yún)?shù)。你可以將輸入驗證的邏輯提取到一個單獨的輔助函數(shù)中。

def validate_input(*types):
    def decorator(func):
        def wrapper(*args, **kwargs):
            if len(args) != len(types):
                raise TypeError("Number of arguments does not match expected types")
            for arg, type_ in zip(args, types):
                if not isinstance(arg, type_):
                    raise TypeError(f"Argument {arg} is not of type {type_}")
            return func(*args, **kwargs)
        return wrapper
    return decorator
def is_positive(number):
    if number <= 0:
        raise ValueError("Number must be positive")
    return number
@validate_input(int, int)
def add(a, b):
    return a + b
@validate_input(int)
def square(n):
    return n ** 2
add(3, 5)  # 正常運行
square(4)  # 正常運行
# square(-4)  # 拋出 ValueError

使用輔助函數(shù)進行緩存

假設(shè)你有一個裝飾器,用于緩存函數(shù)的結(jié)果。你可以將緩存的邏輯提取到一個單獨的輔助函數(shù)中。

from functools import lru_cache
def cache_results(func):
    @lru_cache(maxsize=128)
    def wrapper(*args, **kwargs):
        return func(*args, **kwargs)
    return wrapper
def compute_fibonacci(n):
    if n <= 1:
        return n
    return compute_fibonacci(n - 1) + compute_fibonacci(n - 2)
@cache_results
def fibonacci(n):
    return compute_fibonacci(n)
print(fibonacci(10))  # 輸出: 55
print(fibonacci(10))  # 直接從緩存中獲取結(jié)果

使用輔助函數(shù)進行權(quán)限驗證

假設(shè)你有一個裝飾器,用于驗證用戶是否有權(quán)限調(diào)用某個函數(shù)。你可以將權(quán)限驗證的邏輯提取到一個單獨的輔助函數(shù)中。

def check_permission(permission):
    def decorator(func):
        def wrapper(*args, **kwargs):
            if not has_permission(permission):
                raise PermissionError(f"User does not have permission {permission}")
            return func(*args, **kwargs)
        return wrapper
    return decorator
def has_permission(permission):
    # 假設(shè)這里有一個權(quán)限檢查的邏輯
    return permission == "admin"
@check_permission("admin")
def admin_action():
    print("Performing admin action")
@check_permission("user")
def user_action():
    print("Performing user action")
admin_action()  # 正常運行
# user_action()  # 拋出 PermissionError

使用輔助函數(shù)進行性能測量

假設(shè)你有一個裝飾器,用于測量函數(shù)的執(zhí)行時間。你可以將性能測量的邏輯提取到一個單獨的輔助函數(shù)中。

import time
def measure_time(func):
    def wrapper(*args, **kwargs):
        start_time = time.time()
        result = func(*args, **kwargs)
        end_time = time.time()
        print(f"{func.__name__} took {end_time - start_time:.4f} seconds to execute")
        return result
    return wrapper
def get_current_time():
    return time.time()
@measure_time
def slow_function():
    time.sleep(2)
    print("Slow function completed")
slow_function()

如何在裝飾器中使用多個裝飾器?

基本的多重裝飾器

假設(shè)你有兩個裝飾器 @log_function_call 和 @measure_time,分別用于日志記錄和性能測量。

import logging
import time
# 配置日志記錄
logging.basicConfig(level=logging.INFO)
def log_message(message):
    logging.info(message)
def log_function_call(func):
    def wrapper(*args, **kwargs):
        log_message(f"Calling {func.__name__} with args={args} kwargs={kwargs}")
        result = func(*args, **kwargs)
        log_message(f"{func.__name__} returned {result}")
        return result
    return wrapper
def measure_time(func):
    def wrapper(*args, **kwargs):
        start_time = time.time()
        result = func(*args, **kwargs)
        end_time = time.time()
        print(f"{func.__name__} took {end_time - start_time:.4f} seconds to execute")
        return result
    return wrapper
@log_function_call
@measure_time
def add(a, b):
    time.sleep(1)  # 模擬耗時操作
    return a + b
result = add(3, 5)
print(f"Result: {result}")

帶參數(shù)的多重裝飾器

假設(shè)你有一個帶參數(shù)的裝飾器 @repeat,用于多次調(diào)用函數(shù),同時還有一個 @log_function_call 裝飾器。

import logging
# 配置日志記錄
logging.basicConfig(level=logging.INFO)
def log_message(message):
    logging.info(message)
def log_function_call(func):
    def wrapper(*args, **kwargs):
        log_message(f"Calling {func.__name__} with args={args} kwargs={kwargs}")
        result = func(*args, **kwargs)
        log_message(f"{func.__name__} returned {result}")
        return result
    return wrapper
def repeat(num_times):
    def decorator(func):
        def wrapper(*args, **kwargs):
            results = []
            for _ in range(num_times):
                result = func(*args, **kwargs)
                results.append(result)
            return results
        return wrapper
    return decorator
@log_function_call
@repeat(3)
def greet(name):
    return f"Hello, {name}!"
results = greet("Alice")
for result in results:
    print(result)

使用 functools.wraps 保留元數(shù)據(jù)

為了保留被裝飾函數(shù)的元數(shù)據(jù)(如名稱、文檔字符串等),可以使用 functools.wraps。

import logging
import time
import functools
# 配置日志記錄
logging.basicConfig(level=logging.INFO)
def log_message(message):
    logging.info(message)
def log_function_call(func):
    @functools.wraps(func)
    def wrapper(*args, **kwargs):
        log_message(f"Calling {func.__name__} with args={args} kwargs={kwargs}")
        result = func(*args, **kwargs)
        log_message(f"{func.__name__} returned {result}")
        return result
    return wrapper
def measure_time(func):
    @functools.wraps(func)
    def wrapper(*args, **kwargs):
        start_time = time.time()
        result = func(*args, **kwargs)
        end_time = time.time()
        print(f"{func.__name__} took {end_time - start_time:.4f} seconds to execute")
        return result
    return wrapper
@log_function_call
@measure_time
def add(a, b):
    time.sleep(1)  # 模擬耗時操作
    return a + b
result = add(3, 5)
print(f"Result: {result}")
print(add.__name__)  # 輸出: add
print(add.__doc__)   # 輸出: None 或者函數(shù)的文檔字符串

組合多個帶參數(shù)的裝飾器

假設(shè)你有兩個帶參數(shù)的裝飾器 @repeat 和 @log_level,分別用于多次調(diào)用函數(shù)和設(shè)置日志級別。

import logging
import functools
# 配置日志記錄
logging.basicConfig(level=logging.DEBUG)
def set_log_level(level):
    def decorator(func):
        @functools.wraps(func)
        def wrapper(*args, **kwargs):
            logger = logging.getLogger(func.__name__)
            logger.setLevel(level)
            result = func(*args, **kwargs)
            return result
        return wrapper
    return decorator
def repeat(num_times):
    def decorator(func):
        @functools.wraps(func)
        def wrapper(*args, **kwargs):
            results = []
            for _ in range(num_times):
                result = func(*args, **kwargs)
                results.append(result)
            return results
        return wrapper
    return decorator
@set_log_level(logging.INFO)
@repeat(3)
def greet(name):
    logger = logging.getLogger(greet.__name__)
    logger.info(f"Greeting {name}")
    return f"Hello, {name}!"
results = greet("Alice")
for result in results:
    print(result)

總結(jié)

通過將裝飾器中的復雜邏輯提取到單獨的輔助函數(shù)中,可以使裝飾器更加模塊化和易于維護。這些輔助函數(shù)可以被多個裝飾器復用,從而提高代碼的重用性和可讀性。

通過組合多個裝飾器,可以實現(xiàn)更復雜的功能。多個裝飾器的執(zhí)行順序是從內(nèi)到外,因此最靠近函數(shù)定義的裝飾器會首先被應用。使用 functools.wraps 可以保留被裝飾函數(shù)的元數(shù)據(jù),使代碼更加清晰和易讀。希望這些示例能幫助你更好地理解如何在裝飾器中使用多個裝飾器。

責任編輯:華軒 來源: 測試開發(fā)學習交流
相關(guān)推薦

2022-05-10 09:12:16

TypeScript裝飾器

2010-02-01 17:50:32

Python裝飾器

2022-06-23 08:00:53

PythonDateTime模塊

2025-03-21 09:58:59

Python數(shù)據(jù)類型安全

2020-09-09 07:00:00

TensorFlow神經(jīng)網(wǎng)絡人工智能

2023-02-27 17:36:33

LinuxSIGINT信號

2022-10-13 00:03:00

JavaScripSQL函數(shù)

2025-01-20 08:40:00

Python對象

2023-02-07 07:47:52

Python裝飾器函數(shù)

2011-08-10 09:31:41

Hibernateunion

2021-03-09 07:27:40

Kafka開源分布式

2015-08-27 09:46:09

swiftAFNetworkin

2021-06-09 09:36:18

DjangoElasticSearLinux

2022-05-17 08:25:10

TypeScript接口前端

2024-01-18 08:37:33

socketasyncio線程

2021-06-01 07:19:58

Python函數(shù)裝飾器

2023-08-24 10:24:54

GitLabPodman

2010-03-10 14:03:41

python處理文本

2020-12-08 22:07:08

PythonWebDjango

2021-09-10 10:30:22

Java代碼
點贊
收藏

51CTO技術(shù)棧公眾號