全部学科
Python全栈
python
NodeJS全栈
nodejs
小程序首页
📅 2026-05-19 8 分钟 ✍️ juanwangdev

Python 带参数装饰器

带参数装饰器通过嵌套函数实现,外层接收参数,内层执行装饰逻辑。

基本结构

带参数装饰器需要三层嵌套:

  • 最外层:接收装饰器参数,返回装饰器
  • 中间层:接收被装饰函数,返回包装函数
  • 最内层:执行实际包装逻辑
Python
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 say_hello(name):
    print(f"Hello, {name}!")


say_hello("World")
# 输出:
# Hello, World!
# Hello, World!
# Hello, World!

参数传递方式

位置参数与关键字参数

Python
def log(level="INFO", prefix=""):
    "支持关键字参数的日志装饰器"
    def decorator(func):
        def wrapper(*args, **kwargs):
            print(f"[{level}] {prefix}{func.__name__} called")
            return func(*args, **kwargs)
        return wrapper
    return decorator


@log(level="DEBUG", prefix=">>> ")
def process(data):
    return data * 2


process(10)  # [DEBUG] >>> process called

混合参数形式

Python
def validate(*validators, error_msg="Validation failed"):
    "接收多个验证器参数"
    def decorator(func):
        def wrapper(*args, **kwargs):
            for validator in validators:
                if not validator(*args, **kwargs):
                    raise ValueError(error_msg)
            return func(*args, **kwargs)
        return wrapper
    return decorator


def is_positive(x):
    return x > 0


def is_even(x):
    return x % 2 == 0


@validate(is_positive, is_even, error_msg="必须是正偶数")
def compute(x):
    return x ** 2


compute(4)   # 16
compute(-2)  # ValueError: 必须是正偶数

使用 functools.wraps

带参数装饰器同样需要保留函数元信息:

Python
from functools import wraps


def retry(max_attempts=3, delay=1):
    "重试装饰器"
    def decorator(func):
        @wraps(func)  # 保留元信息
        def wrapper(*args, **kwargs):
            for attempt in range(max_attempts):
                try:
                    return func(*args, **kwargs)
                except Exception as e:
                    if attempt == max_attempts - 1:
                        raise
                    print(f"Attempt {attempt + 1} failed, retrying...")
        return wrapper
    return decorator


@retry(max_attempts=2)
def risky_operation():
    import random
    if random.random() < 0.5:
        raise ValueError("Random failure")
    return "Success"

类方式实现

使用类实现带参数装饰器更加清晰:

Python
class RateLimit:
    "限流装饰器"

    def __init__(self, calls=10, period=60):
        self.calls = calls
        self.period = period
        self.timestamps = []

    def __call__(self, func):
        @wraps(func)
        def wrapper(*args, **kwargs):
            import time
            now = time.time()
            # 清理过期时间戳
            self.timestamps = [t for t in self.timestamps if now - t < self.period]
            if len(self.timestamps) >= self.calls:
                raise RuntimeError("Rate limit exceeded")
            self.timestamps.append(now)
            return func(*args, **kwargs)
        return wrapper


@RateLimit(calls=5, period=60)
def api_call(endpoint):
    return f"Calling {endpoint}"

要点总结

特性说明
结构三层嵌套:工厂函数 → 装饰器 → 包装函数
参数支持位置参数、关键字参数、可变参数
元信息使用 @wraps(func) 保留被装饰函数属性
类实现__init__ 接收参数,__call__ 返回包装函数

带参数装饰器的核心是返回一个真正的装饰器,装饰器再返回包装函数。

D:\git2\jwdev\articles\PYTHON\进阶\装饰器深入\带参数装饰器.md

📝 发现内容有误?点击此处直接编辑

← 上一篇 Python functools.wraps
下一篇 → Python 类装饰器
想查看更多题目和详细解析?
小程序提供完整的题库、模拟考试和详细解析
马上就来

长按或扫描二维码,立即体验

扫码体验小程序
马上就来
使用微信扫描二维码
立即体验完整题库