简介
Python 装饰器是强大的工具,它允许开发者在不改变函数核心实现的情况下修改或增强函数。本教程将探讨使用带可变参数的装饰器的高级技术,深入了解如何创建更灵活、动态的函数包装器,以处理不同的参数配置。
Python 装饰器是强大的工具,它允许开发者在不改变函数核心实现的情况下修改或增强函数。本教程将探讨使用带可变参数的装饰器的高级技术,深入了解如何创建更灵活、动态的函数包装器,以处理不同的参数配置。
在 Python 中,装饰器是一种强大且优雅的方式,用于在不直接更改函数和方法源代码的情况下对其进行修改或增强。它们本质上是将另一个函数作为参数,并返回该函数的修改版本的函数。
def my_decorator(func):
def wrapper():
print("函数调用前执行的操作。")
func()
print("函数调用后执行的操作。")
return wrapper
@my_decorator
def say_hello():
print("你好!")
say_hello()
在 Python 中,函数是一等公民,这意味着它们可以:
| 概念 | 描述 |
|---|---|
| 包装函数 | 一个为原始函数添加功能的函数 |
| @装饰器语法 | 应用装饰器的语法糖 |
| 函数闭包 | 允许装饰器维护状态和上下文 |
装饰器通常用于:
def uppercase_decorator(func):
def wrapper():
original_result = func()
return original_result.upper()
return wrapper
@uppercase_decorator
def greet():
return "你好,LabEx 学习者!"
print(greet()) ## 输出:HELLO, LABEX LEARNER!
虽然装饰器提供了很大的灵活性,但由于额外的函数调用,它们确实会带来一些小的性能开销。对于对性能要求较高的代码,需要考虑这一开销。
functools.wraps 来保留元数据通过理解这些基础知识,你将为在下一节中探索更高级的装饰器技术做好充分准备。
装饰器可以使用 *args 和 **kwargs 来处理不同类型的函数签名,从而实现灵活的参数传递。
def debug_decorator(func):
def wrapper(*args, **kwargs):
print(f"正在调用 {func.__name__}")
print(f"位置参数: {args}")
print(f"关键字参数: {kwargs}")
result = func(*args, **kwargs)
print(f"结果: {result}")
return result
return wrapper
@debug_decorator
def calculate_total(a, b, tax=0.1):
return a + b + (a + b) * tax
calculate_total(100, 200, tax=0.15)
| 策略 | 描述 | 使用场景 |
|---|---|---|
| *args | 捕获位置参数 | 参数数量未知 |
| **kwargs | 捕获关键字参数 | 灵活的函数签名 |
| 组合使用 | 处理两种类型的参数 | 最大程度的灵活性 |
def type_check(expected_type):
def decorator(func):
def wrapper(*args, **kwargs):
for arg in args:
if not isinstance(arg, expected_type):
raise TypeError(f"预期类型为 {expected_type},实际得到 {type(arg)}")
return func(*args, **kwargs)
return wrapper
return decorator
@type_check(int)
def multiply(a, b):
return a * b
multiply(4, 5) ## 正常运行
## multiply(4, "5") ## 引发 TypeError
from functools import wraps
def metadata_preserving_decorator(func):
@wraps(func)
def wrapper(*args, **kwargs):
"""包装函数文档"""
return func(*args, **kwargs)
return wrapper
def labex_timer(func):
import time
def wrapper(*args, **kwargs):
start = time.time()
result = func(*args, **kwargs)
end = time.time()
print(f"LabEx 性能: {func.__name__} 耗时 {end - start} 秒")
return result
return wrapper
@labex_timer
def complex_computation(n):
return sum(i**2 for i in range(n))
complex_computation(10000)
通过掌握装饰器中的可变参数,你可以创建高度灵活且强大的函数包装器,以适应不同的函数签名和使用场景。
类装饰器提供了一种动态修改或增强整个类的方法。
def singleton(cls):
instances = {}
def get_instance(*args, **kwargs):
if cls not in instances:
instances[cls] = cls(*args, **kwargs)
return instances[cls]
return get_instance
@singleton
class DatabaseConnection:
def __init__(self):
self.connection = "Active"
def bold(func):
def wrapper():
return f"<b>{func()}</b>"
return wrapper
def italic(func):
def wrapper():
return f"<i>{func()}</i>"
return wrapper
@bold
@italic
def greet():
return "你好,LabEx!"
| 装饰器类型 | 描述 | 复杂度 |
|---|---|---|
| 简单型 | 无参数 | 低 |
| 参数化型 | 接受配置参数 | 中等 |
| 基于类型 | 使用类结构 | 高 |
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 display_message():
print("LabEx 学习平台")
def authenticated(role):
def decorator(func):
def wrapper(*args, **kwargs):
user_role = get_current_user_role()
if user_role == role:
return func(*args, **kwargs)
else:
raise PermissionError("未经授权的访问")
return wrapper
return decorator
@authenticated(role='admin')
def delete_user(user_id):
## 删除逻辑
pass
def memoize(func):
cache = {}
def wrapper(*args):
if args not in cache:
cache[args] = func(*args)
return cache[args]
return wrapper
@memoize
def fibonacci(n):
if n < 2:
return n
return fibonacci(n-1) + fibonacci(n-2)
import time
import functools
def performance_tracker(func):
@functools.wraps(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
functools.wrapsdef error_handler(func):
def wrapper(*args, **kwargs):
try:
return func(*args, **kwargs)
except Exception as e:
print(f"{func.__name__} 中出现错误: {e}")
## 可选择记录或处理错误
return wrapper
通过掌握这些高级装饰器模式,你可以创建强大、灵活且可维护的 Python 代码,充分发挥装饰器的潜力。
通过掌握 Python 中带可变参数的装饰器,开发者可以创建更通用、可复用的代码。本教程涵盖的技术展示了如何处理不同类型的参数、实现灵活的函数修改,以及充分利用 Python 装饰器功能的全部潜力来编写更优雅、高效的代码。