如何处理带多个参数的装饰器

PythonPythonBeginner
立即练习

💡 本教程由 AI 辅助翻译自英文原版。如需查看原文,您可以 切换至英文原版

简介

Python 装饰器是强大的工具,使开发者能够在不直接更改函数源代码的情况下修改或增强函数。本教程探讨用于处理多个参数的高级装饰器技术,为开发者提供创建更灵活、动态的函数包装器的全面策略。


Skills Graph

%%%%{init: {'theme':'neutral'}}%%%% flowchart RL python(("Python")) -.-> python/FunctionsGroup(["Functions"]) python(("Python")) -.-> python/AdvancedTopicsGroup(["Advanced Topics"]) python/FunctionsGroup -.-> python/function_definition("Function Definition") python/FunctionsGroup -.-> python/arguments_return("Arguments and Return Values") python/FunctionsGroup -.-> python/lambda_functions("Lambda Functions") python/FunctionsGroup -.-> python/scope("Scope") python/AdvancedTopicsGroup -.-> python/decorators("Decorators") subgraph Lab Skills python/function_definition -.-> lab-419675{{"如何处理带多个参数的装饰器"}} python/arguments_return -.-> lab-419675{{"如何处理带多个参数的装饰器"}} python/lambda_functions -.-> lab-419675{{"如何处理带多个参数的装饰器"}} python/scope -.-> lab-419675{{"如何处理带多个参数的装饰器"}} python/decorators -.-> lab-419675{{"如何处理带多个参数的装饰器"}} end

装饰器基础

什么是装饰器?

在 Python 中,装饰器是一种强大且优雅的方式,用于在不直接更改函数或类的源代码的情况下对其进行修改或增强。它允许你用另一个函数来包装一个函数,动态地添加额外的功能。

基本装饰器语法

一个基本的装饰器遵循以下基本结构:

def my_decorator(func):
    def wrapper():
        ## 在原始函数执行之前执行的代码
        func()  ## 调用原始函数
        ## 在原始函数执行之后执行的代码
    return wrapper

@my_decorator
def original_function():
    print("原始函数正在运行")

简单装饰器示例

让我们演示一个简单的性能计时装饰器:

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} 秒")
        return result
    return wrapper

@timer_decorator
def slow_function():
    time.sleep(2)
    print("慢速函数完成")

slow_function()

装饰器工作流程

graph TD A[原始函数] --> B[装饰器包装器] B --> C{预处理} C --> D[调用原始函数] D --> E{后处理} E --> F[返回结果]

装饰器的关键特性

特性 描述
可重用性 可以应用于多个函数
非侵入性 不修改原始函数代码
可扩展性 可以添加多层功能

常见用例

装饰器通常用于:

  • 日志记录
  • 性能测量
  • 认证
  • 缓存
  • 输入验证

通过理解这些基础知识,你就可以准备好在 LabEx Python 编程课程中探索更高级的装饰器技术了。

带参数的装饰器

理解装饰器参数

装饰器可以接受参数以提供更大的灵活性和定制性。创建带参数的装饰器主要有两种方式:

  1. 接受函数参数的装饰器
  2. 接受自身参数的装饰器

接受函数参数的装饰器

def validate_args(func):
    def wrapper(*args, **kwargs):
        for arg in args:
            if not isinstance(arg, int):
                raise TypeError(f"预期为整数,得到的是 {type(arg)}")
        return func(*args, **kwargs)
    return wrapper

@validate_args
def add_numbers(a, b):
    return a + b

print(add_numbers(3, 4))  ## 正常工作
## print(add_numbers(3, "4"))  ## 引发TypeError

带自定义参数的装饰器

def repeat(times):
    def decorator(func):
        def wrapper(*args, **kwargs):
            for _ in range(times):
                result = func(*args, **kwargs)
            return result
        return wrapper
    return decorator

@repeat(times=3)
def greet(name):
    print(f"你好,{name}!")

greet("LabEx")

装饰器参数流程

graph TD A[装饰器参数] --> B[装饰器工厂] B --> C[装饰器包装器] C --> D[原始函数] D --> E[返回结果]

装饰器参数类型

参数类型 描述 示例
位置参数 固定位置的参数 @repeat(3)
关键字参数 命名参数 @validate(min_length=5)
混合参数 位置参数和关键字参数的组合 @custom_decorator(10, strict=True)

高级参数处理

def log_calls(log_level='INFO'):
    def decorator(func):
        def wrapper(*args, **kwargs):
            print(f"[{log_level}] 调用 {func.__name__}")
            return func(*args, **kwargs)
        return wrapper
    return decorator

@log_calls(log_level='DEBUG')
def complex_calculation(x, y):
    return x * y

complex_calculation(5, 6)

最佳实践

  • 对复杂的参数处理使用嵌套函数
  • 使用 functools.wraps 保留原始函数的元数据
  • 保持装饰器逻辑简洁且专注
  • 优雅地处理不同的参数场景

通过掌握带参数的装饰器,你将在 Python 中解锁强大的元编程技术,提升你在 LabEx 编程项目中代码的灵活性和可重用性。

实用装饰器示例

缓存装饰器

from functools import lru_cache

@lru_cache(maxsize=100)
def fibonacci(n):
    if n < 2:
        return n
    return fibonacci(n-1) + fibonacci(n-2)

print(fibonacci(100))  ## 计算速度极快

认证装饰器

def authenticate(role='user'):
    def decorator(func):
        def wrapper(*args, **kwargs):
            user_role = 'admin'  ## 模拟认证
            if user_role == role:
                return func(*args, **kwargs)
            else:
                raise PermissionError("未经授权的访问")
        return wrapper
    return decorator

@authenticate(role='admin')
def delete_system_files():
    print("系统文件已删除")

delete_system_files()

性能监测装饰器

import time
import functools

def performance_monitor(func):
    @functools.wraps(func)
    def wrapper(*args, **kwargs):
        start = time.perf_counter()
        result = func(*args, **kwargs)
        end = time.perf_counter()
        print(f"{func.__name__} 执行耗时 {end - start:.4f} 秒")
        return result
    return wrapper

@performance_monitor
def complex_computation(n):
    return sum(i**2 for i in range(n))

complex_computation(1000000)

装饰器工作流程

graph TD A[装饰器] --> B[输入验证] B --> C[性能跟踪] C --> D[认证] D --> E[缓存] E --> F[原始函数]

实际应用中的装饰器

用例 描述 示例
日志记录 跟踪函数调用 捕获方法调用
速率限制 控制函数执行频率 API 请求管理
输入验证 确保数据完整性 类型和范围检查
重试机制 自动错误恢复 网络请求处理

带指数退避的重试装饰器

import time
from functools import wraps

def retry(max_attempts=3, delay=1):
    def decorator(func):
        @wraps(func)
        def wrapper(*args, **kwargs):
            attempts = 0
            while attempts < max_attempts:
                try:
                    return func(*args, **kwargs)
                except Exception as e:
                    attempts += 1
                    if attempts == max_attempts:
                        raise
                    wait = delay * (2 ** attempts)
                    time.sleep(wait)
        return wrapper
    return decorator

@retry(max_attempts=3, delay=2)
def unstable_network_request():
    ## 模拟网络请求
    import random
    if random.random() < 0.7:
        raise ConnectionError("网络不稳定")
    return "成功"

unstable_network_request()

高级装饰器技术

  • 组合多个装饰器
  • 创建基于类的装饰器
  • 使用 functools.wraps 保留元数据
  • 处理复杂的参数场景

通过探索这些实际示例,你将深入了解装饰器在 LabEx Python 编程中的多功能性,从而实现更健壮、高效的代码设计。

总结

通过掌握带多个参数的装饰器,Python 开发者可以创建更复杂且可复用的代码结构。本教程展示了如何实现能接受各种参数类型、增强函数行为并提升整体代码模块化和可维护性的复杂装饰器。