当涉及到带有参数的装饰器时,需要在装饰器内再套一层函数。这样的装饰器可以接受参数,并根据参数的不同采取不同的行为。
以下是一个带有参数的装饰器的示例:
def repeat(n):
def decorator(func):
def wrapper(*args, **kwargs):
for _ in range(n):
result = func(*args, **kwargs)
return result
return wrapper
return decorator
@repeat(3)
def greet(name):
print(f"Hello, {name}!")
# 调用被装饰后的函数
greet("Alice")
在这个例子中,repeat
是一个带有参数的装饰器。它返回一个装饰器函数 decorator
,这个函数接受被装饰的函数 func
作为参数,并返回一个新的函数 wrapper
。这个新的函数在调用原始函数前后重复执行了 n
次。
整个过程可以总结为:
-
定义带参数的装饰器: 定义一个高阶函数(
repeat
),它接受装饰器参数,并返回真正的装饰器函数(decorator
)。 -
定义包装函数: 在装饰器函数内部定义一个新的函数(
wrapper
),这个函数负责在调用原始函数前后执行额外的代码。 -
返回包装函数: 装饰器函数返回包装函数,替换了原始函数。
-
使用带参数的装饰器: 使用
@decorator_name(argument)
语法将装饰器应用于函数,或者手动调用decorator_name(argument)(func)
。
带参数的装饰器使得我们可以更灵活地定制装饰器的行为。这在处理不同函数或场景时尤其有用。
使用场景:
装饰器在许多场景中都非常有用,它们提供了一种灵活的方式来修改或扩展函数的行为。以下是一些常见的使用场景:
-
日志记录: 记录函数的输入、输出或运行时间,以便进行调试或性能分析。
def log_function_call(func):
def wrapper(*args, **kwargs):
result = func(*args, **kwargs)
print(f"Function {func.__name__} called with args: {args}, kwargs: {kwargs}. Result: {result}")
return result
return wrapper
@log_function_call
def add(a, b):
return a + b
- 性能分析: 测量函数的执行时间,帮助找到代码中的性能瓶颈。
import time
def measure_time(func):
def wrapper(*args, **kwargs):
start_time = time.time()
result = func(*args, **kwargs)
end_time = time.time()
print(f"Function {func.__name__} took {end_time - start_time} seconds to run.")
return result
return wrapper
@measure_time
def heavy_computation():
# Some computationally intensive task
pass
- 权限验证: 检查用户权限或角色,并根据情况允许或拒绝访问某个函数或资源。
def require_admin(func):
def wrapper(*args, **kwargs):
if is_admin():
return func(*args, **kwargs)
else:
raise PermissionError("Admin access required.")
return wrapper
@require_admin
def delete_user(user_id):
# Delete user logic
pass
- 缓存: 缓存函数的输出,避免重复计算。
def memoize(func):
cache = {}
def wrapper(*args, **kwargs):
key = (args, frozenset(kwargs.items()))
if key not in cache:
cache[key] = func(*args, **kwargs)
return cache[key]
return wrapper
@memoize
def fibonacci(n):
if n <= 1:
return n
else:
return fibonacci(n-1) + fibonacci(n-2)
- 事务管理: 在函数执行前后进行事务的开启和提交,或者在出现异常时进行回滚。
def transactional(func):
def wrapper(*args, **kwargs):
start_transaction()
try:
result = func(*args, **kwargs)
commit_transaction()
return result
except Exception as e:
rollback_transaction()
raise e
return wrapper
@transactional
def transfer_funds(sender, recipient, amount):
# Transfer funds logic
pass
- 重试机制: 在函数执行失败时,自动重试,增强系统的鲁棒性。
import time
def retry_on_error(max_retries=3, delay=1):
def decorator(func):
def wrapper(*args, **kwargs):
retries = 0
while retries < max_retries:
try:
result = func(*args, **kwargs)
return result
except Exception as e:
print(f"Error: {e}. Retrying...")
time.sleep(delay)
retries += 1
raise RuntimeError(f"Failed after {max_retries} retries.")
return wrapper
return decorator
@retry_on_error()
def potentially_failing_function():
# Some code that might fail
pass
- 输入验证: 检查函数输入参数的有效性,确保满足预期条件。
def validate_inputs(*types):
def decorator(func):
def wrapper(*args, **kwargs):
for arg, arg_type in zip(args, types):
if not isinstance(arg, arg_type):
raise TypeError(f"Expected {arg_type}, but got {type(arg)} for argument {arg}.")
return func(*args, **kwargs)
return wrapper
return decorator
@validate_inputs(str, int)
def example_function(name, age):
# Function logic
pass
- 单例模式: 确保类只有一个实例,通过装饰器来实现单例模式。
def singleton(cls):
instances = {}
def wrapper(*args, **kwargs):
if cls not in instances:
instances[cls] = cls(*args, **kwargs)
return instances[cls]
return wrapper
@singleton
class MyClass:
pass
- 参数化装饰器: 装饰器也可以接受参数,使其更加灵活和通用。
def repeat(n=2):
def decorator(func):
def wrapper(*args, **kwargs):
for _ in range(n):
result = func(*args, **kwargs)
return result
return wrapper
return decorator
@repeat(3)
def greet(name):
print(f"Hello, {name}!")
- 动态注册插件: 使用装饰器来动态注册插件,实现插件式架构。
plugins = []
def register_plugin(func):
plugins.append(func)
return func
@register_plugin
def my_plugin():
# Plugin logic
pass
# 使用注册的插件
for plugin in plugins:
plugin()
- 打印函数执行时间: 使用装饰器记录函数执行时间,用于性能优化。
import time
def timing_decorator(func):
def wrapper(*args, **kwargs):
start_time = time.time()
result = func(*args, **kwargs)
end_time = time.time()
print(f"{func.__name__} took {end_time - start_time:.2f} seconds to run.")
return result
return wrapper
@timing_decorator
def long_running_function():
# Some time-consuming task
pass
- 异步装饰器: 适用于异步函数的装饰器,允许在异步代码中添加功能。
import asyncio
def async_decorator(func):
async def wrapper(*args, **kwargs):
print("Before async function")
result = await func(*args, **kwargs)
print("After async function")
return result
return wrapper
@async_decorator
async def async_example():
# Async function logic
pass