本文目录导读:

我来详细讲解 Python 装饰器传参的几种常见方式。
基础装饰器(无参数)
def simple_decorator(func):
def wrapper(*args, **kwargs):
print("执行前")
result = func(*args, **kwargs)
print("执行后")
return result
return wrapper
@simple_decorator
def greet(name):
return f"你好, {name}"
# 使用
print(greet("Alice"))
# 输出:
# 执行前
# 执行后
# 你好, Alice
装饰器本身传参
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("Bob")
# 输出:
# Hello, Bob
# Hello, Bob
# Hello, Bob
向被装饰函数传参
def validate_args(*expected_types):
def decorator(func):
def wrapper(*args, **kwargs):
# 验证位置参数的类型
for arg, expected_type in zip(args, expected_types):
if not isinstance(arg, expected_type):
raise TypeError(f"参数 {arg} 类型错误,期望 {expected_type}")
return func(*args, **kwargs)
return wrapper
return decorator
@validate_args(int, int)
def add(a, b):
return a + b
# 使用
print(add(1, 2)) # 3
# print(add(1, "2")) # 会抛出 TypeError
实际案例:日志装饰器
import functools
import time
def log(logger=None, level='INFO'):
"""
带参数的日志装饰器
:param logger: 日志对象
:param level: 日志级别
"""
def decorator(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
start_time = time.time()
# 记录调用信息
if logger:
log_msg = f"[{level}] 调用 {func.__name__} - args: {args}, kwargs: {kwargs}"
logger.log(log_msg)
else:
print(f"[{level}] 调用 {func.__name__}")
try:
result = func(*args, **kwargs)
elapsed = time.time() - start_time
if logger:
logger.log(f"[{level}] {func.__name__} 执行完成,耗时: {elapsed:.4f}s")
else:
print(f"[{level}] {func.__name__} 执行完成,耗时: {elapsed:.4f}s")
return result
except Exception as e:
if logger:
logger.log(f"[ERROR] {func.__name__} 执行失败: {e}")
raise
return wrapper
return decorator
# 使用示例
class SimpleLogger:
def log(self, msg):
print(f"Logger: {msg}")
@log(logger=SimpleLogger(), level='DEBUG')
def calculate(x, y):
return x * y
calculate(5, 3)
缓存装饰器
import functools
def cache(maxsize=128):
"""
带最大缓存大小的缓存装饰器
"""
def decorator(func):
cache_dict = {}
@functools.wraps(func)
def wrapper(*args, **kwargs):
# 创建缓存键
key = str(args) + str(sorted(kwargs.items()))
if key in cache_dict:
print(f"使用缓存: {key}")
return cache_dict[key]
result = func(*args, **kwargs)
# 缓存管理
if len(cache_dict) >= maxsize:
# 移除最早添加的项
first_key = next(iter(cache_dict))
del cache_dict[first_key]
cache_dict[key] = result
return result
return wrapper
return decorator
@cache(maxsize=3)
def fibonacci(n):
if n < 2:
return n
return fibonacci(n-1) + fibonacci(n-2)
# 使用
print(fibonacci(10)) # 计算并缓存
print(fibonacci(10)) # 使用缓存
同时处理装饰器和被装饰函数参数
def permission_required(permission):
"""
权限验证装饰器
"""
def decorator(func):
def wrapper(user, *args, **kwargs):
if not user.get(permission, False):
raise PermissionError(f"用户没有 {permission} 权限")
return func(user, *args, **kwargs)
return wrapper
return decorator
@permission_required("admin")
def delete_user(user, user_id):
print(f"管理员 {user['name']} 删除用户 {user_id}")
# 使用
admin = {"name": "Admin", "admin": True}
user = {"name": "User", "admin": False}
delete_user(admin, 1) # 正常执行
# delete_user(user, 2) # 抛出 PermissionError
高级案例:重试装饰器
import random
import time
def retry(max_retries=3, delay=1, backoff=2):
"""
重试装饰器
:param max_retries: 最大重试次数
:param delay: 初始延迟时间
:param backoff: 延迟倍数
"""
def decorator(func):
def wrapper(*args, **kwargs):
current_delay = delay
last_exception = None
for attempt in range(max_retries + 1):
try:
return func(*args, **kwargs)
except Exception as e:
last_exception = e
if attempt < max_retries:
print(f"第 {attempt + 1} 次重试,等待 {current_delay} 秒...")
time.sleep(current_delay)
current_delay *= backoff
raise last_exception
return wrapper
return decorator
@retry(max_retries=3, delay=1, backoff=2)
def unstable_api_call():
if random.random() < 0.7: # 70% 概率失败
raise ConnectionError("连接失败")
return "成功"
# 使用
try:
result = unstable_api_call()
print(f"结果: {result}")
except Exception as e:
print(f"最终失败: {e}")
参数传递示意图
@decorator(args) # 装饰器参数
def func(x, y): # 被装饰函数参数
pass
等效于:
decorator(args)(func)(x, y)
关键要点
-
三层嵌套结构:
- 最外层:接收装饰器参数
- 中间层:接收被装饰函数
- 内层:接收被装饰函数的参数
-
参数优先级:
- 装饰器参数:在装饰时确定
- 函数参数:在调用时传递
-
保持函数签名:
- 使用
@functools.wraps(func)保留原函数信息
- 使用
-
灵活设计:
- 可以组合多个装饰器
- 支持默认参数
- 考虑错误处理
通过这些案例,你可以根据实际需求灵活设计带参数的 Python 装饰器。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播