
本文共 3489 字,大约阅读时间需要 11 分钟。
Python 装饰器入门指南
装饰器是 Python 中一个强大的工具,能够帮助开发者在不修改现有函数代码的情况下,增添新的功能。这种功能让你的代码更加简洁、可维护且更符合 Python 的范式。以下将引导你逐步理解装饰器的概念、用法以及实际应用场景。
一、装饰器的基础概念
装饰器(Decorator)是一种函数,用于修改或扩展另一个函数的行为。在 Python 中,装饰器可以是普通函数或者类,能够通过嵌套或参数传递来实现对目标函数的装饰。
装饰器的基本结构:
def a_new_decorator(func): def wrapped(*args, **kwargs): # 在函数执行前后做一些额外的事情 return func(*args, **kwargs) return wrapped
当使用装饰器时,函数被装饰后返回的一般函数对象,就像 wrapped
中定义的函数。wrapped
可以执行额外的操作,然后调用原始函数 func
。
二、使用装饰器的步骤
定义装饰器:
首先,定义一个装饰器函数,该函数接收目标函数作为参数。
装饰目标函数:
使用 @装饰器名
的语法在函数定义处应用装饰器,等价于:
target_function = 装饰器名(target_function)
调用装饰后的函数:
由于装饰器返回的是一个函数对象,直接调用该函数即可。
示例:
def hi(name="yasoob"): return f"hi {name}"@decorator # 装饰器尚未定义,请继续阅读def target(): return "target executed"
def decorator(func): def wrapper(): print("Before executing the decorated function") func() print("After executing the decorated function") return wrappertarget = decorator(target)
调用 target()
时,将执行装饰器应用后的 wrapper
函数,打印日志并调用原函数。
三、带参数的装饰器
装饰器可以接受参数,提供灵活性。这些参数通常用于自定义装饰器的行为,如日志的级别或文件路径。
def logit(logfile='out.log'): def decorator(func): @wraps(func) def wrapper(*args, **kwargs): log_str = f" Func: {func.__name__} was called" print(log_str) with open(logfile, 'a') as f: f.write(log_str + '\n') return func(*args, **kwargs) return wrapper return decorator@logit(logfile='app.log')def foo(): pass# 调用 foo() 则会记录日志到 app.logfoo()
四、使用 functools.wraps
维护元信息
在装饰器应用后,原函数的元信息(如名称、文档字符串)会被替换。为了保留这些信息,可以使用 functools.wraps
装饰器:
from functools import wrapsdef logged(func): @wraps(func) def wrapper(*args, **kwargs): print(f"logged: {func.__name__}") return func(*args, **kwargs) return wrapper@loggeddef bar(x): """bar函数的描述文档""" return x + x# 调用 bar 的时候,会打印 bar 的名称和文档bar(5)
输出:
logged: bar5 +5 = 10
五、类装饰器
装饰器不仅限于函数,还可以是类。类装饰器通常通过 __call__
方法实现,能够装饰函数或其他对象。
示例:
class Logit: def __init__(self, logfile='out.log'): self.logfile = logfile def __call__(self, func): @wraps(func) def wrapper(*args, **kwargs): log_str = f"{func.__name__} was called" print(log_str) with open(self.logfile, 'a') as f: f.write(f"{log_str}\n") return func(*args, **kwargs) return wrapper@Logit(logfile='func.log')def baz(): passbaz()
六、多层装饰器
装饰器可以通过链式调用,逐层增加功能。
def first_decorator(func): def first_wrap(*args, **kwargs): print("First decorator executed") return func(*args, **kwargs) return first_wrapdef second_decorator(func): def second_wrap(*args, **kwargs): print("Second decorator executed") return first_decorator(func)(*args, **kwargs) return second_wrap@second_decorator@first_decoratordef target(): print("Target function") pass# 调用顺序等效于:# target = first_decorator(target)# target = second_decorator(target)# 但输出是:# 第二 decorator 执行 --> 第一个 decorator 执行 --> 目标函数执行# 输出顺序:# Second decorator executed# First decorator executed# Target function
七、装饰器的实际应用场景
日志记录: 在函数执行前后打印日志,帮助调试和监控程序运行。
性能 profiling: 统计函数执行时间,分析性能瓶颈。
权限控制: 检查用户身份,允许或拒绝访问特定资源。
缓存机制: 在函数外层添加缓存,减少后端数据请求。
异常处理: 在函数执行过程中捕捉异常,提供回滚或重试机制。
连接池管理: 为数据库连接或 API 请求创建连接池,避免资源耗尽。
通过这些案例,可以看出装饰器在提升代码复用性、可读性和可维护性的同时,有效支持了 OO 设计的需求。
八、总结
装饰器是 Python 开发中的强大工具,它允许你在不修改原函数代码的情况下,灵活添加功能和行为。掌握装饰器的使用不仅能提升代码质量,还能使你的编程效率大幅提升。建议在实际项目中,从简单的日志装饰器入手,逐步尝试复杂的场景,熟悉装饰器的灵活性和强大功能。
发表评论
最新留言
关于作者
