带参数的Python装饰器原来这么简单,5分钟彻底掌握!

带参数的装饰器(三层嵌套结构)

python 复制代码
def repeat_execution(n_times):
    # 第一层:接收装饰器参数
    def decorator(func):
        # 第二层:接收被装饰函数
        def wrapper(*args, **kwargs):
            # 第三层:执行装饰逻辑
            for _ in range(n_times):
                result = func(*args, **kwargs)
            return result
        return wrapper
    return decorator

@repeat_execution(n_times=3)
def say_hello(name):
    print(f"Hello, {name}!")

say_hello("Alice")

输出:

复制代码
Hello, Alice!
Hello, Alice!
Hello, Alice!

深度解析:装饰器参数如何传递

  1. @repeat_execution(n_times=3) 首先执行
    • 调用repeat_execution(3)返回decorator函数
  2. 接着执行@decorator
    • say_hello作为参数传递给decorator
  3. 最终生成装饰后的wrapper函数

带状态记录的装饰器

python 复制代码
def log_performance(metric_name):
    def decorator(func):
        func.call_count = 0  # 添加函数属性
        
        def wrapper(*args, **kwargs):
            func.call_count += 1
            print(f"[{metric_name}] 执行 #{func.call_count}")
            return func(*args, **kwargs)
        return wrapper
    return decorator

@log_performance("用户验证")
def authenticate(user):
    return user == "admin"

print(authenticate("guest"))
print(authenticate("admin"))
print(f"验证函数调用次数: {authenticate.call_count}")

输出:

ini 复制代码
[用户验证] 执行 #1
False
[用户验证] 执行 #2
True
验证函数调用次数: 2

类实现的装饰器参数

python 复制代码
class TimeoutRetry:
    def __init__(self, retries=3, delay=1):
        self.retries = retries
        self.delay = delay
    
    def __call__(self, func):
        import time
        def wrapper(*args, **kwargs):
            for attempt in range(self.retries):
                try:
                    return func(*args, **kwargs)
                except TimeoutError:
                    print(f"超时重试中... ({attempt+1}/{self.retries})")
                    time.sleep(self.delay)
            raise Exception("所有重试均失败")
        return wrapper

@TimeoutRetry(retries=2, delay=0.5)
def fetch_data():
    # 模拟网络请求
    raise TimeoutError("连接超时")

fetch_data()  # 将触发重试机制

装饰器参数的最佳实践

  1. 命名规范 :使用描述性的参数名(如max_retries而非n

  2. 参数验证 :在装饰器最外层验证参数有效性

    python 复制代码
    def validate_params(max_time):
        if max_time <= 0:
            raise ValueError("最大时间必须为正数")
  3. 保留元数据 :使用@functools.wraps保持原始函数属性

    python 复制代码
    from functools import wraps
    
    def debug_decorator(level):
        def decorator(func):
            @wraps(func)  # 保留原始函数信息
            def wrapper(*args, **kwargs):
                if level > 1:
                    print(f"[DEBUG] 调用 {func.__name__}")
                return func(*args, **kwargs)
            return wrapper
        return decorator
相关推荐
太过平凡的小蚂蚁几秒前
Kotlin 协程中常见的异步返回与控制方式(速览)
开发语言·前端·kotlin
景彡先生29 分钟前
Python函数定义与调用全解析:从基础语法到实战技巧
linux·开发语言·python
m***记42 分钟前
Python字符串操作:如何判断子串是否存在
linux·服务器·python
咖啡の猫1 小时前
Vue初始化脚手架
前端·javascript·vue.js
晨枫阳1 小时前
uniapp兼容问题处理总结
前端·vue.js·uni-app
小白银子1 小时前
零基础从头教学Linux(Day 56)
linux·运维·python
B站计算机毕业设计之家2 小时前
计算机视觉:python手写数字识别系统 手写数字检测 CNN算法 卷积神经网络 OpenCV和Keras模型 大数据毕业设计(建议收藏)✅
python·神经网络·opencv·计算机视觉·cnn·手写数字·数字识别
B站计算机毕业设计之家2 小时前
Python手势识别检测系统 基于MediaPipe的改进SSD算法 opencv+mediapipe 深度学习 大数据 (建议收藏)✅
python·深度学习·opencv·计算机视觉·1024程序员节
liusheng2 小时前
腾讯地图 SDK 接入到 uniapp 的多端解决方案
前端·uni-app
拉不动的猪2 小时前
如何处理管理系统中(Vue PC + uni-app 移动端):业务逻辑复用基本方案
前端·javascript·架构