如何实现带参数的装饰器

PythonPythonBeginner
立即练习

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

简介

Python 装饰器是用于修改和增强函数行为而不改变其核心实现的强大工具。本教程探讨了创建带参数装饰器的高级技术,为开发者提供了在 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-438211{{"如何实现带参数的装饰器"}} python/arguments_return -.-> lab-438211{{"如何实现带参数的装饰器"}} python/lambda_functions -.-> lab-438211{{"如何实现带参数的装饰器"}} python/scope -.-> lab-438211{{"如何实现带参数的装饰器"}} python/decorators -.-> lab-438211{{"如何实现带参数的装饰器"}} end

装饰器基础

什么是装饰器?

Python 中的装饰器是一种强大的方式,可以在不直接更改函数和方法源代码的情况下对其进行修改或增强。它们本质上是将另一个函数作为参数,并返回该函数的修改版本的函数。

基本装饰器语法

def my_decorator(func):
    def wrapper():
        print("函数调用前的一些操作。")
        func()
        print("函数调用后的一些操作。")
    return wrapper

@my_decorator
def say_hello():
    print("你好!")

say_hello()

装饰器如何工作

graph TD A[原始函数] --> B[装饰器函数] B --> C[包装函数] C --> D[修改后的函数行为]

关键概念

概念 描述
包装函数 用于添加功能的内部函数
@装饰器语法 应用装饰器的语法糖
函数闭包 保留外部函数的状态

带参数的装饰器

def decorator_with_args(arg1, arg2):
    def actual_decorator(func):
        def wrapper(*args, **kwargs):
            print(f"装饰器参数: {arg1}, {arg2}")
            return func(*args, **kwargs)
        return wrapper
    return actual_decorator

@decorator_with_args("你好", 42)
def example_function(x):
    print(f"函数使用以下参数调用: {x}")

example_function(10)

常见用例

  1. 日志记录
  2. 函数计时
  3. 认证
  4. 缓存
  5. 输入验证

最佳实践

  • 保持装饰器简单且功能集中
  • 使用 functools.wraps 保留元数据
  • 避免意外修改函数行为

注意:在探索装饰器时,LabEx 为 Python 开发和学习高级编程概念提供了一个优秀的环境。

带参数的装饰器

理解带参数的装饰器

带参数的装饰器允许你将参数传递给装饰器本身,从而在函数修改中提供更大的灵活性和定制性。

带参数装饰器的基本结构

def decorator_with_params(param1, param2):
    def actual_decorator(func):
        def wrapper(*args, **kwargs):
            ## 使用param1和param2的装饰器逻辑
            print(f"装饰器参数: {param1}, {param2}")
            return func(*args, **kwargs)
        return wrapper
    return actual_decorator

装饰器流程可视化

graph TD A[装饰器参数] --> B[装饰器函数] B --> C[包装函数] C --> D[原始函数] D --> E[修改后的函数行为]

实际示例

具有可配置日志级别的日志装饰器

def log_decorator(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_decorator('DEBUG')
def calculate_sum(a, b):
    return a + b

result = calculate_sum(5, 3)

装饰器参数类型

参数类型 描述 示例
字符串 控制日志记录或行为 @decorator('debug')
布尔值 启用/禁用功能 @decorator(enabled=True)
整数 设置限制或阈值 @decorator(max_retries=3)
函数 传递自定义逻辑 @decorator(validator=custom_func)

高级用例:速率限制装饰器

import time
from functools import wraps

def rate_limit(max_calls, time_frame):
    def decorator(func):
        calls = []
        @wraps(func)
        def wrapper(*args, **kwargs):
            current_time = time.time()
            calls[:] = [call for call in calls if current_time - call < time_frame]

            if len(calls) >= max_calls:
                raise Exception("速率限制超出")

            calls.append(current_time)
            return func(*args, **kwargs)
        return wrapper
    return decorator

@rate_limit(max_calls=3, time_frame=60)
def api_request():
    print("API请求已处理")

关键注意事项

  1. 使用 functools.wraps 保留函数元数据
  2. 优雅地处理不同的参数类型
  3. 确保装饰器行为清晰且可预测

注意:LabEx 提供了一个交互式平台,用于探索和实践高级 Python 装饰器技术。

实际应用

性能监控装饰器

import time
import functools

def performance_monitor(func):
    @functools.wraps(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

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

认证和授权装饰器

def require_auth(role='user'):
    def decorator(func):
        @functools.wraps(func)
        def wrapper(*args, **kwargs):
            ## 模拟认证检查
            current_user_role = 'admin'
            if current_user_role!= role:
                raise PermissionError("权限不足")
            return func(*args, **kwargs)
        return wrapper
    return decorator

@require_auth('admin')
def delete_user(user_id):
    print(f"正在删除用户 {user_id}")

缓存装饰器实现

def memoize(func):
    cache = {}
    @functools.wraps(func)
    def wrapper(*args):
        if args not in cache:
            cache[args] = func(*args)
        return cache[args]
    return wrapper

@memoize
def fibonacci(n):
    if n < 2:
        return n
    return fibonacci(n-1) + fibonacci(n-2)

装饰器应用场景

场景 装饰器用途 主要优点
日志记录 跟踪函数调用 调试、监控
缓存 存储函数结果 性能优化
认证 控制访问 安全管理
重试机制 处理临时故障 弹性
输入验证 验证函数输入 数据完整性

综合示例:重试机制

import time
from random import random

def retry(max_attempts=3, delay=1):
    def decorator(func):
        @functools.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
                    time.sleep(delay * attempts)
        return wrapper
    return decorator

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

装饰器组合

graph TD A[原始函数] --> B[性能监控器] B --> C[认证] C --> D[重试机制] D --> E[最终执行]

最佳实践

  1. 保持装饰器功能集中且单一用途
  2. 使用 functools.wraps 保留函数元数据
  3. 优雅地处理异常
  4. 考虑性能影响

注意:LabEx 为探索和实践 Python 中的高级装饰器技术提供了一个优秀的环境。

总结

通过理解如何实现带参数的装饰器,Python 开发者可以创建更具动态性和灵活性的代码结构。本教程展示了装饰器的多功能性,说明了如何使用它们以最小的代码复杂度来添加可配置功能、日志记录、性能跟踪以及其他高级编程技术。