老生常谈Python进阶之装饰器
发布时间 - 2026-01-11 01:04:18 点击率:次函数也是对象

要理解Python装饰器,首先要明白在Python中,函数也是一种对象,因此可以把定义函数时的函数名看作是函数对象的一个引用。既然是引用,因此可以将函数赋值给一个变量,也可以把函数作为一个参数传递或返回。同时,函数体中也可以再定义函数。
装饰器本质
可以通过编写一个纯函数的例子来还原装饰器所要做的事。
def decorator(func):
def wrap():
print("Doing someting before executing func()")
func()
print("Doing someting after executing func()")
return wrap
def fun_test():
print("func")
fun_test = decorator(fun_test)
fun_test()
# Output:
# Doing someting before executing func()
# func
# Doing someting after executing func()
fun_test所指向的函数的引用传递给decorator()函数
decorator()函数中定义了wrap()子函数,这个子函数会调用通过func引用传递进来的fun_test()函数,并在调用函数的前后做了一些其他的事情
decorator()函数返回内部定义的wrap()函数引用
fun_test接收decorator()返回的函数引用,从而指向了一个新的函数对象
通过fun_test()调用新的函数执行wrap()函数的功能,从而完成了对fun_test()函数的前后装饰
Python中使用装饰器
在Python中可以通过@符号来方便的使用装饰器功能。
def decorator(func):
def wrap():
print("Doing someting before executing func()")
func()
print("Doing someting after executing func()")
return wrap
@decorator
def fun_test():
print("func")
fun_test()
# Output:
# Doing someting before executing func()
# func
# Doing someting after executing func()
装饰的功能已经实现了,但是此时执行:
print(fun_test.__name__) # Output: # wrap
fun_test.__name__已经变成了wrap,这是应为wrap()函数已经重写了我们函数的名字和注释文档。此时可以通过functools.wraps来解决这个问题。wraps接受一个函数来进行装饰,并加入了复制函数名称、注释文档、参数列表等等功能。这可以让我们在装饰器里面访问在装饰之前的函数的属性。
更规范的写法:
from functools import wraps
def decorator(func):
@wraps(func)
def wrap():
print("Doing someting before executing func()")
func()
print("Doing someting after executing func()")
return wrap
@decorator
def fun_test():
print("func")
fun_test()
print(fun_test.__name__)
# Output:
# Doing someting before executing func()
# func
# Doing someting after executing func()
# fun_test
带参数的装饰器
通过返回一个包裹函数的函数,可以模仿wraps装饰器,构造出一个带参数的装饰器。
from functools import wraps
def loginfo(info='info1'):
def loginfo_decorator(func):
@wraps(func)
def wrap_func(*args, **kwargs):
print(func.__name__ + ' was called')
print('info: %s' % info)
return func(*args, **kwargs)
return wrap_func
return loginfo_decorator
@loginfo()
def func1():
pass
func1()
# Output:
# func1 was called
# info: info1
@loginfo(info='info2')
def func2():
pass
func2()
# Output:
# func2 was called
# info: info2
装饰器类
通过编写类的方法也可以实现装饰器,并让装饰器具备继承等面向对象中更实用的特性
首先编写一个装饰器基类:
from functools import wraps
class loginfo:
def __init__(self, info='info1'):
self.info = info
def __call__(self, func):
@wrap
def wrap_func(*args, **kwargs):
print(func.__name__ + ' was called')
print('info: %s' % self.info)
self.after() # 调用after方法,可以在子类中实现
return func(*args, **kwargs)
return wrap_func
def after(self):
pass
@loginfo(info='info2')
def func1():
pass
# Output:
# func1 was called
# info: info1
再通过继承loginfo类,扩展装饰器的功能:
class loginfo_after(loginfo):
def __init__(self, info2='info2', *args, **kwargs):
self.info2 = info2
super(loginfo_after, self).__init__(*args, **kwargs)
def after(self):
print('after: %s' % self.info2)
@loginfo_after()
def func2():
pass
func2()
# Output:
# func2 was called
# info: info1
# after: info2
以上这篇老生常谈Python进阶之装饰器就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持。
# python
# 装饰器
# python装饰器使用实例详解
# python 一篇文章搞懂装饰器所有用法(建议收藏)
# python类装饰器用法实例
# Python装饰器模式定义与用法分析
# python中装饰器级连的使用方法示例
# python如何实现不用装饰器实现登陆器小程序
# python装饰器代替set get方法实例
# 可以通过
# 给大家
# 进阶
# 这是
# 文档
# 让我们
# 老生常谈
# 其他的
# 子函数
# 并在
# 希望能
# 要做
# 写了
# 作为一个
# 可以实现
# 中也
# 这篇
# 这可
# 小编
# 解决这个问题
相关栏目:
【
网站优化151355 】
【
网络推广146373 】
【
网络技术251813 】
【
AI营销90571 】
相关推荐:
广州网站制作公司哪家好一点,广州欧莱雅百库网络科技有限公司官网?
Laravel怎么连接多个数据库_Laravel多数据库连接配置
制作ppt免费网站有哪些,有哪些比较好的ppt模板下载网站?
高性价比服务器租赁——企业级配置与24小时运维服务
如何快速查询域名建站关键信息?
网站制作价目表怎么做,珍爱网婚介费用多少?
如何在局域网内绑定自建网站域名?
JS中对数组元素进行增删改移的方法总结
Laravel Debugbar怎么安装_Laravel调试工具栏配置指南
laravel怎么在请求结束后执行任务(Terminable Middleware)_laravel Terminable Middleware请求结束任务执行方法
三星、SK海力士获美批准:可向中国出口芯片制造设备
Laravel如何使用Sanctum进行API认证?(SPA实战)
Python自然语言搜索引擎项目教程_倒排索引查询优化案例
怎么制作一个起泡网,水泡粪全漏粪育肥舍冬季氨气超过25ppm,可以有哪些措施降低舍内氨气水平?
微信h5制作网站有哪些,免费微信H5页面制作工具?
Laravel如何监控和管理失败的队列任务_Laravel失败任务处理与监控
如何用y主机助手快速搭建网站?
如何在腾讯云免费申请建站?
js实现获取鼠标当前的位置
如何快速选择适合个人网站的云服务器配置?
如何快速查询网址的建站时间与历史轨迹?
海南网站制作公司有哪些,海口网是哪家的?
公司门户网站制作公司有哪些,怎样使用wordpress制作一个企业网站?
如何自己制作一个网站链接,如何制作一个企业网站,建设网站的基本步骤有哪些?
使用spring连接及操作mongodb3.0实例
北京网站制作费用多少,建立一个公司网站的费用.有哪些部分,分别要多少钱?
标题:Vue + Vuex + JWT 身份认证的正确实践与常见误区解析
如何确保FTP站点访问权限与数据传输安全?
Win11怎么恢复误删照片_Win11数据恢复工具使用【推荐】
如何在 React 中条件性地遍历数组并渲染元素
百度浏览器ai对话怎么关 百度浏览器ai聊天窗口隐藏
Laravel如何获取当前登录用户信息_Laravel Auth门面使用与Session用户读取【技巧】
网站页面设计需要考虑到这些问题
如何快速生成ASP一键建站模板并优化安全性?
如何安全更换建站之星模板并保留数据?
详解Nginx + Tomcat 反向代理 负载均衡 集群 部署指南
Laravel如何优雅地处理服务层_在Laravel中使用Service层和Repository层
Laravel怎么实现一对多关联查询_Laravel Eloquent模型关系定义与预加载【实战】
Laravel如何实现API资源集合?(Resource Collection教程)
移动端脚本框架Hammer.js
详解Android图表 MPAndroidChart折线图
北京网站制作的公司有哪些,北京白云观官方网站?
香港代理服务器配置指南:高匿IP选择、跨境加速与SEO优化技巧
专业企业网站设计制作公司,如何理解商贸企业的统一配送和分销网络建设?
专业型网站制作公司有哪些,我设计专业的,谁给推荐几个设计师兼职类的网站?
Win11怎么开启自动HDR画质_Windows11显示设置HDR选项
Python文本处理实践_日志清洗解析【指导】
如何基于PHP生成高效IDC网络公司建站源码?
Laravel如何实现邮箱地址验证功能_Laravel邮件验证流程与配置
b2c电商网站制作流程,b2c水平综合的电商平台?

