上一篇
在带参数的函数中使用Python装饰器 - 详细教程
- Python
- 2025-07-30
- 749
Python带参函数中使用装饰器的高级指南
装饰器是Python中一种强大的功能,它允许开发者修改或增强函数的行为而不改变函数本身。本教程将重点介绍如何在带参数的函数中使用装饰器,包括装饰器的基础知识、带参数的装饰器实现以及在类方法中的应用。
一、装饰器基础回顾
在深入带参函数之前,我们先回顾装饰器的基本工作原理:
def simple_decorator(func):
def wrapper():
print("函数执行前")
func()
print("函数执行后")
return wrapper
@simple_decorator
def greet():
print("Hello, World!")
greet()
二、在带参函数中使用装饰器
当被装饰的函数带有参数时,我们需要在装饰器的内部函数中处理这些参数:
def log_decorator(func):
def wrapper(*args, **kwargs):
print(f"调用函数: {func.__name__}")
print(f"参数: {args}, {kwargs}")
result = func(*args, **kwargs)
print(f"返回值: {result}")
return result
return wrapper
@log_decorator
def add(a, b):
return a + b
@log_decorator
def greet(name, message="你好"):
return f"{message}, {name}!"
print(add(5, 3))
print(greet("张三", message="欢迎"))
关键点解析:
- 使用
*args
和**kwargs
接受任意参数 - 在内部函数中调用原始函数时传递所有参数
- 返回原始函数的执行结果
三、带参数的装饰器
装饰器本身也可以接受参数,这需要三层嵌套函数:
def repeat(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(n_times=3)
def say_hello(name):
print(f"Hello, {name}!")
say_hello("李四")
工作流程:
repeat(n_times)
返回装饰器函数- 装饰器函数接受被装饰的函数作为参数
- 内部
wrapper
函数处理函数调用
四、类方法中的装饰器
在类中使用装饰器时,需要处理self
参数:
def method_decorator(func):
def wrapper(self, *args, **kwargs):
print(f"调用方法: {self.__class__.__name__}.{func.__name__}")
return func(self, *args, **kwargs)
return wrapper
class Calculator:
@method_decorator
def add(self, a, b):
return a + b
@method_decorator
def multiply(self, a, b):
return a * b
calc = Calculator()
print(calc.add(10, 20))
print(calc.multiply(5, 6))
五、保留函数元信息
使用装饰器后,原始函数的元信息会被覆盖,使用functools.wraps
解决:
from functools import wraps
def preserve_metadata(func):
@wraps(func)
def wrapper(*args, **kwargs):
"""包装函数的文档字符串"""
print(f"调用函数: {func.__name__}")
return func(*args, **kwargs)
return wrapper
@preserve_metadata
def example(a: int, b: int) -> int:
"""两个数字相加"""
return a + b
print(example.__name__) # 输出 'example'
print(example.__doc__) # 输出 '两个数字相加'
print(example.__annotations__) # 输出 {'a': <class 'int'>, 'b': <class 'int'>, 'return': <class 'int'>}
六、实际应用场景
1. 缓存函数结果
def cache(func):
cached_results = {}
@wraps(func)
def wrapper(*args, **kwargs):
key = (args, frozenset(kwargs.items()))
if key not in cached_results:
cached_results[key] = func(*args, **kwargs)
return cached_results[key]
return wrapper
@cache
def fibonacci(n):
if n <= 1:
return n
return fibonacci(n-1) + fibonacci(n-2)
print(fibonacci(10))
2. 权限验证
def requires_role(role):
def decorator(func):
@wraps(func)
def wrapper(*args, **kwargs):
user = kwargs.get('user', None)
if user and user.get('role') == role:
return func(*args, **kwargs)
else:
raise PermissionError(f"需要 {role} 权限")
return wrapper
return decorator
@requires_role('admin')
def delete_user(user_id, user=None):
print(f"删除用户 {user_id}")
admin_user = {'name': 'Admin', 'role': 'admin'}
regular_user = {'name': 'User', 'role': 'user'}
delete_user(123, user=admin_user) # 成功
delete_user(456, user=regular_user) # 抛出异常
总结
装饰器是Python中强大且灵活的工具,特别是在处理带参数的函数时。关键要点包括:
✓ 使用*args
和**kwargs
处理任意参数
✓ 使用functools.wraps
保留函数元数据
✓ 三层嵌套函数实现带参数的装饰器
✓ 在类方法中正确处理self
参数
掌握这些技巧将大大提高代码的可重用性和可维护性。
本文由DiaoYanSi于2025-07-30发表在吾爱品聚,如有疑问,请联系我们。
本文链接:https://www.521pj.cn/20256888.html
发表评论