简介
Python 装饰器是用于在不改变函数核心实现的情况下修改函数行为的强大工具。本教程将探讨链接多个装饰器的高级技术,展示开发者如何创建复杂的函数包装器,并提高代码的模块化和可重用性。
Python 装饰器是用于在不改变函数核心实现的情况下修改函数行为的强大工具。本教程将探讨链接多个装饰器的高级技术,展示开发者如何创建复杂的函数包装器,并提高代码的模块化和可重用性。
在 Python 中,装饰器是一种强大且灵活的方式,用于修改或增强函数和方法,而无需直接更改其源代码。本质上,装饰器是一种函数,它接受另一个函数作为参数,并返回该函数的修改版本。
以下是 Python 中一个简单的装饰器示例:
def my_decorator(func):
def wrapper():
print("函数调用前执行的某些操作。")
func()
print("函数调用后执行的某些操作。")
return wrapper
@my_decorator
def say_hello():
print("你好!")
say_hello()
当这段代码运行时,它将输出:
函数调用前执行的某些操作。
你好!
函数调用后执行的某些操作。
Python 中有几种类型的装饰器:
| 装饰器类型 | 描述 | 示例用例 |
|---|---|---|
| 函数装饰器 | 修改函数行为 | 日志记录、计时、认证 |
| 类装饰器 | 修改类行为 | 单例模式、类注册 |
| 方法装饰器 | 修改方法行为 | 缓存、验证 |
装饰器也可以处理带参数的函数:
def log_function(func):
def wrapper(*args, **kwargs):
print(f"调用函数:{func.__name__}")
return func(*args, **kwargs)
return wrapper
@log_function
def add(a, b):
return a + b
result = add(3, 5)
print(result)
@ 语法以便于应用通过理解装饰器,你可以编写更具模块化和可重用性的代码,使你的 Python 程序更加灵活和强大。
装饰器链允许将多个装饰器应用于单个函数。当你链接装饰器时,它们从下往上应用,从而创建了一种组合多种行为的强大方式。
@decorator1
@decorator2
@decorator3
def my_function():
pass
def bold(func):
def wrapper():
return f"<b>{func()}</b>"
return wrapper
def italic(func):
def wrapper():
return f"<i>{func()}</i>"
return wrapper
def underline(func):
def wrapper():
return f"<u>{func()}</u>"
return wrapper
@bold
@italic
@underline
def greet():
return "你好,LabEx!"
print(greet())
## 输出:<b><i><u>你好,LabEx!</u></i></b>
对于接受参数的装饰器,链接会变得更加复杂:
def repeat(times):
def decorator(func):
def wrapper(*args, **kwargs):
for _ in range(times):
result = func(*args, **kwargs)
return result
return wrapper
return decorator
def log_call(func):
def wrapper(*args, **kwargs):
print(f"调用 {func.__name__}")
return func(*args, **kwargs)
return wrapper
@repeat(3)
@log_call
def say_hello(name):
print(f"你好,{name}!")
say_hello("LabEx 用户")
| 注意事项 | 描述 |
|---|---|
| 顺序很重要 | 装饰器从下往上应用 |
| 复杂度 | 更多的装饰器可能会增加函数的复杂度 |
| 性能 | 多个装饰器可能会有轻微的性能开销 |
import functools
def my_decorator(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
return func(*args, **kwargs)
return wrapper
装饰器链不仅仅是一个理论概念,而是一种强大的技术,在软件开发中有许多实际应用。
def require_login(func):
def wrapper(*args, **kwargs):
if not is_user_authenticated():
raise PermissionError("需要登录")
return func(*args, **kwargs)
return wrapper
def log_performance(func):
def wrapper(*args, **kwargs):
start_time = time.time()
result = func(*args, **kwargs)
end_time = time.time()
print(f"{func.__name__} 执行耗时 {end_time - start_time} 秒")
return result
return wrapper
@require_login
@log_performance
def sensitive_operation():
## 复杂的数据库或 API 操作
pass
def validate_input(validator):
def decorator(func):
def wrapper(*args, **kwargs):
if not validator(*args, **kwargs):
raise ValueError("无效输入")
return func(*args, **kwargs)
return wrapper
return decorator
def convert_to_type(target_type):
def decorator(func):
def wrapper(*args, **kwargs):
result = func(*args, **kwargs)
return target_type(result)
return wrapper
return decorator
@convert_to_type(int)
@validate_input(lambda x: x > 0)
def process_number(value):
return value * 2
def retry(max_attempts=3):
def decorator(func):
def wrapper(*args, **kwargs):
attempts = 0
while attempts < max_attempts:
try:
return func(*args, **kwargs)
except Exception as e:
attempts += 1
if attempts == max_attempts:
raise e
return wrapper
return decorator
def cache_result(func):
cache = {}
def wrapper(*args):
if args not in cache:
cache[args] = func(*args)
return cache[args]
return wrapper
@retry(max_attempts=3)
@cache_result
def fetch_data(url):
## 模拟网络请求
pass
| 实践 | 描述 | 建议 |
|---|---|---|
| 顺序很重要 | 从特定到一般应用装饰器 | 自下而上的方法 |
| 性能 | 最小化装饰器复杂度 | 避免繁重的计算 |
| 可读性 | 保持装饰器专注 | 单一职责原则 |
import time
import functools
def timeit(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
start = time.perf_counter()
result = func(*args, **kwargs)
end = time.perf_counter()
print(f"{func.__name__} 耗时 {end - start:.4f} 秒")
return result
return wrapper
def profile_memory(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
import tracemalloc
tracemalloc.start()
result = func(*args, **kwargs)
current, peak = tracemalloc.get_traced_memory()
print(f"{func.__name__} 内存使用情况:当前 {current},峰值 {peak}")
tracemalloc.stop()
return result
return wrapper
@timeit
@profile_memory
def complex_computation():
## 计算任务
pass
掌握 Python 中的装饰器链,能使开发者创建灵活且动态的函数修改。通过理解装饰器的应用顺序并运用实际技术,程序员可以编写更优雅、易于维护且高效的代码,充分利用 Python 强大的元编程能力。