【Python】解析Python中的装饰器
python中的函数也是对象,函数可以被当作变量传递。
装饰器在python中功能非常强大,装饰器允许对原有函数行为进行扩展,而不用硬编码的方式,它提供了一种面向切面的访问方式。
装饰器
一个普通的装饰器一般是这样:
import functools def log(func): @functools.wraps(func) def wrapper(*args, **kwargs): print('call %s():' % func.__name__) print('args = {}'.format(*args)) return func(*args, **kwargs) return wrapper
这样就定义了一个打印出方法名及其参数的装饰器。
调用之:
@log def test(p): print(test.__name__ + " param: " + p) test("I'm a param")
输出:
call test():
args = I'm a param
test param: I'm a param
装饰器在使用时,用了@语法,让人有些困扰。其实,装饰器只是个方法,与下面的调用方式没有区别:
def test(p): print(test.__name__ + " param: " + p) wrapper = log(test) wrapper("I'm a param")
@语法只是将函数传入装饰器函数,并无神奇之处。
值得注意的是@functools.wraps(func),这是python提供的装饰器。它能把原函数的元信息拷贝到装饰器里面的 func 函数中。函数的元信息包括docstring、name、参数列表等等。可以尝试去除@functools.wraps(func),你会发现test.__name__的输出变成了wrapper。
带参数的装饰器
装饰器允许传入参数,一个携带了参数的装饰器将有三层函数,如下所示:
import functools def log_with_param(text): def decorator(func): @functools.wraps(func) def wrapper(*args, **kwargs): print('call %s():' % func.__name__) print('args = {}'.format(*args)) print('log_param = {}'.format(text)) return func(*args, **kwargs) return wrapper return decorator @log_with_param("param") def test_with_param(p): print(test_with_param.__name__)
看到这个代码是不是又有些疑问,内层的decorator函数的参数func是怎么传进去的?和上面一般的装饰器不大一样啊。
其实道理是一样的,将其@语法去除,恢复函数调用的形式一看就明白了:
# 传入装饰器的参数,并接收返回的decorator函数 decorator = log_with_param("param") # 传入test_with_param函数 wrapper = decorator(test_with_param) # 调用装饰器函数 wrapper("I'm a param")
输出结果与正常使用装饰器相同:
call test_with_param():
args = I'm a param
log_param = param
test_with_param
至此,装饰器这个有点费解的特性也没什么神秘了。
装饰器这一语法体现了Python中函数是第一公民,函数是对象、是变量,可以作为参数、可以是返回值,非常的灵活与强大。
原文链接:
https://www.jianshu.com/p/ee82b941772a
https://www.geeksforgeeks.org/decorators-in-python/
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· C#/.NET/.NET Core技术前沿周刊 | 第 29 期(2025年3.1-3.9)
· 从HTTP原因短语缺失研究HTTP/2和HTTP/3的设计差异