Python 装饰器的 10 个应用场景详解
装饰器本质上是一个高阶函数,它接受一个函数作为参数并返回一个新函数。通过使用 @ 符号语法糖,我们可以将装饰器应用于任何函数或类,从而在不修改原函数代码的前提下增强其功能。在实际开发中,合理使用装饰器可以显著提高代码的可读性和可维护性。
在使用自定义装饰器时,建议结合 来保留原函数的元数据(如名称、文档字符串等),避免调试困难。
本文详细介绍了 Python 装饰器的核心概念及十大应用场景,包括日志记录、性能测试、数据缓存、输入验证、授权认证、参数修改、错误处理、单例模式、事件监听和异步编程。文章提供了完整的代码示例,涵盖了基础用法、带参数装饰器、类装饰器以及调试注意事项。通过合理使用装饰器,开发者可以在不修改原代码的情况下增强函数功能,提升代码的可维护性和扩展性。

装饰器本质上是一个高阶函数,它接受一个函数作为参数并返回一个新函数。通过使用 @ 符号语法糖,我们可以将装饰器应用于任何函数或类,从而在不修改原函数代码的前提下增强其功能。在实际开发中,合理使用装饰器可以显著提高代码的可读性和可维护性。
在使用自定义装饰器时,建议结合 来保留原函数的元数据(如名称、文档字符串等),避免调试困难。
functools.wrapsimport functools
def my_decorator(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
print("Something is happening before the function is called.")
result = func(*args, **kwargs)
print("Something is happening after the function is called.")
return result
return wrapper
@my_decorator
def say_hello():
"""Say hello"""
print("Hello!")
say_hello()
装饰器可以用来记录函数的调用细节,这在调试和监控应用时非常有用。通过记录输入参数和返回值,可以快速定位问题。
import logging
logging.basicConfig(level=logging.INFO)
def log_decorator(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
logging.info(f"{func.__name__} was called with args={args}, kwargs={kwargs}")
result = func(*args, **kwargs)
logging.info(f"{func.__name__} returned {result}")
return result
return wrapper
@log_decorator
def add(x, y):
return x + y
使用装饰器来测量函数执行时间,对于性能分析和瓶颈定位非常有用。
import time
def timing_decorator(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
start_time = time.time()
result = func(*args, **kwargs)
end_time = time.time()
elapsed = end_time - start_time
print(f"{func.__name__} took {elapsed:.4f} seconds")
return result
return wrapper
装饰器可以用于缓存函数的结果,避免重复计算,特别适用于纯函数(Pure Functions)。Python 标准库提供了 lru_cache 实现。
from functools import lru_cache
@lru_cache(maxsize=128)
def fib(n):
if n < 2:
return n
return fib(n-1) + fib(n-2)
确保函数接收有效输入,可以在函数内部逻辑之前进行类型检查或范围校验,提高健壮性。
def validate_decorator(func):
@functools.wraps(func)
def wrapper(x, y):
if not isinstance(x, int) or not isinstance(y, int):
raise TypeError("Input must be integers")
return func(x, y)
return wrapper
@validate_decorator
def multiply(x, y):
return x * y
检查用户是否有执行函数的权限,常用于 Web 框架中的路由保护或 API 接口鉴权。
def auth_decorator(required_role='admin'):
def decorator(func):
@functools.wraps(func)
def wrapper(user, *args, **kwargs):
if user.get('role') == required_role:
return func(user, *args, **kwargs)
else:
raise PermissionError("You do not have permission")
return wrapper
return decorator
@auth_decorator(required_role='admin')
def delete_resource(user, resource_id):
pass
修改函数的输入参数,例如统一格式化时间戳或转换数据类型。
def modify_args_decorator(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
# Example: Double all numeric arguments
new_args = [arg * 2 if isinstance(arg, (int, float)) else arg for arg in args]
return func(*new_args, **kwargs)
return wrapper
捕获函数中的异常并进行处理,防止程序崩溃,同时记录错误堆栈信息。
def error_handling_decorator(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
try:
return func(*args, **kwargs)
except Exception as e:
print(f"Error occurred in {func.__name__}: {e}")
return None
return wrapper
确保类的实例只创建一次,常用于数据库连接池或配置管理器。
def singleton(cls):
instances = {}
@functools.wraps(cls)
def wrapper(*args, **kwargs):
if cls not in instances:
instances[cls] = cls(*args, **kwargs)
return instances[cls]
return wrapper
@singleton
class Database:
def __init__(self):
self.connection = "Connected"
在特定事件发生时执行额外的操作,常用于解耦业务逻辑与通知逻辑。
def event_listener(event_name):
def decorator(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
# Simulate event check
if True:
return func(*args, **kwargs)
return wrapper
return decorator
使同步函数能够异步执行,或者为异步函数添加等待逻辑,配合 asyncio 使用。
import asyncio
async def async_decorator(func):
@functools.wraps(func)
async def wrapper(*args, **kwargs):
await asyncio.sleep(0.1)
return await func(*args, **kwargs)
return wrapper
@async_decorator
async def fetch_data():
return "Data"
当需要传递参数给装饰器本身时,需要使用三层嵌套函数。
def repeat(times):
def decorator(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
for _ in range(times):
func(*args, **kwargs)
return wrapper
return decorator
除了函数装饰器,还可以使用类来实现装饰器逻辑,通常用于更复杂的状态管理。
class CountCalls:
def __init__(self, func):
functools.update_wrapper(self, func)
self.func = func
self.count = 0
def __call__(self, *args, **kwargs):
self.count += 1
print(f"Call {self.count} of {self.func.__name__}")
return self.func(*args, **kwargs)
@CountCalls
def say_hi():
print("Hi")
在使用装饰器时,如果未正确使用 functools.wraps,会导致 __name__ 和 __doc__ 丢失,增加调试难度。此外,多层装饰器叠加时,需要注意执行顺序:从内到外依次包裹。在生产环境中,应充分考虑装饰器对性能的影响,避免在高频调用的路径上引入过重的逻辑。
装饰器是 Python 中一个强大而灵活的工具,它可以在不改变原有代码结构的前提下,为函数增加额外的功能。通过掌握装饰器的使用,你可以使你的 Python 代码更加高效、优雅和可维护。注意在生产环境中使用装饰器时,应充分考虑其对性能的影响以及异常处理的完备性。

微信公众号「极客日志」,在微信中扫描左侧二维码关注。展示文案:极客日志 zeeklog
解析常见 curl 参数并生成 fetch、axios、PHP curl 或 Python requests 示例代码。 在线工具,curl 转代码在线工具,online
将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online
将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online
将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online
将 HTML 片段转为 GitHub Flavored Markdown,支持标题、列表、链接、代码块与表格等;浏览器内处理,可链接预填。 在线工具,HTML转Markdown在线工具,online
通过删除不必要的空白来缩小和压缩JSON。 在线工具,JSON 压缩在线工具,online