1. 先看一段代码

def is_login(func):
def foo(*args,**kwargs):
return func(*args,**kwargs)
return foo def test():
print('我是:',test.__name__) @is_login
def test1():
print('我是:',test1.__name__)
@is_login
def test2():
print('我是:',test2.__name__) test()
test1()
test2() >>>> 我是: test
我是: foo
我是: foo

可以发现函数的函数名即 name已被装饰器改变

2.那我们来增加@wraps

from functools import wraps

def is_login(func):
@wraps(func)
def foo(*args,**kwargs):
return func(*args,**kwargs)
return foo def test():
print('我是:',test.__name__) @is_login
def test1():
print('我是:',test1.__name__)
@is_login
def test2():
print('我是:',test2.__name__) test()
test1()
test2() >>>>
我是: test
我是: test1
我是: test2

结论:

可以看见@wraps可以保证装饰器修饰的函数的name的值保持不变


补充:装饰的优化

以时间装饰器为例,进行优化

  • 装饰器的统一模板
from functools import wraps
# 对函数的装饰器, 对类func最好为cls
def decorate(func):
@wraps(func)
# 增添或修改功能的函数
def wrapper(*args,**kwargs):
# 执行被装饰的函数
result = func(*args,**kwargs)
# 返回结果
return result
# 返回内层函数
return wrapper

普通--时间装饰器

from functools import wraps
import time
from random import randint def use_time(func):
@wraps(func)
def wrapper(*args,**kwargs):
st_time = time.time()
result = func(*args,**kwargs)
end_time = time.time()
print(f'{func.__name__}函数use_time:{end_time-st_time}s')
return wrapper @use_time
def foo():
time.sleep(randint(1,3)) for _ in range(3):
foo() #输出
>>>>
foo函数use_time:1.0007495880126953s
foo函数use_time:3.0018675327301025s
foo函数use_time:3.0030477046966553s

下面对改装饰器进行优化(解耦)

  • 可以发先上面时间装饰器计算的结果,只能在控制台上打印
  • 那我们怎样才能将它输出为日志呢???
  • 我们需要将他的结果进行自定输出
# 在增加一层函数
from functools import wraps
import time
from random import randint def record(output):
def use_time(func):
@wraps(func)
def wrapper(*args,**kwargs):
st_time = time.time()
result = func(*args,**kwargs)
end_time = time.time()
# print(f'{func.__name__}函数use_time:{end_time-st_time}s')
output(func.__name__, end_time-st_time)
return wrapper
return use_time # 改装饰器的结果就可以自定义了,下面以print函数为例
@record(print)
def foo():
time.sleep(randint(2,5)) for _ in range(3):
foo()
>>>>
foo 3.000645875930786
foo 4.003818988800049
foo 2.0020666122436523

结果输出日志

  • 只需要自己定义一个函数
def write_log(name,content):
with open('./time.log','a')as f:
f.write(f'{name}耗时:{content}\r\n') # \r\n 换行 # 只需要将装饰器改为@record(write_log)
@record(write_log)
def foo():
time.sleep(randint(2,5)) for _ in range(3):
foo()

效果如下

 
效果如图

作者:憧憬001
链接:https://www.jianshu.com/p/5df1769e562e
来源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。

对装饰器@wraps的解释(一看就懂)-- 并对装饰器详解的更多相关文章

  1. libsvm的安装,数据格式,常见错误,grid.py参数选择,c-SVC过程,libsvm参数解释,svm训练数据,libsvm的使用详解,SVM核函数的选择

    直接conda install libsvm安装的不完整,缺几个.py文件. 第一种安装方法: 下载:http://www.csie.ntu.edu.tw/~cjlin/cgi-bin/libsvm. ...

  2. Appium+python自动化(三十一)- 元芳,你怎么看? - 日志收集-logging(超详解)

    简介 生活中的日志是记录你生活的点点滴滴,让它把你内心的世界表露出来,更好的诠释自己的内心世界,而电脑里的日志是有价值的信息宝库. 日志文件是专门用于记录系统操作事件的记录文件或文件集合,操作系统有操 ...

  3. RF射频传输,原理介绍,三分钟看懂!发射功率、接收灵敏度详解!

    射频是什么? 官方说法:RF,Radio Frequency. (不懂的人,看了还是不懂,不过对于物联网行业的开发工程师.产品经理和项目经理,还是有需要对射频有个基础了解的.) 燚智能解读: 两个人, ...

  4. 怎样看K线图(实图详解)

    K线图由开盘价.收盘价.最高价和最低价组成.       上面两种图叫作实体红K线和实体黑K线,实体红K线意味买力强劲,市场有强烈的做多欲望,此时可持股待涨.实体黑K线则代表市场完全进入恐惧状态,如果 ...

  5. python装饰器中functools.wraps的作用详解

    直接上代码看效果: # 定义一个最简单的装饰器 def user_login_data(f): def wrapper(*args, **kwargs): return f(*args, **kwar ...

  6. 【转】详解Python的装饰器

    原文链接:http://python.jobbole.com/86717/ Python中的装饰器是你进入Python大门的一道坎,不管你跨不跨过去它都在那里. 为什么需要装饰器 我们假设你的程序实现 ...

  7. 详解Python的装饰器

    Python中的装饰器是你进入Python大门的一道坎,不管你跨不跨过去它都在那里. 为什么需要装饰器 我们假设你的程序实现了say_hello()和say_goodbye()两个函数. def sa ...

  8. Python装饰器详解

    python中的装饰器是一个用得非常多的东西,我们可以把一些特定的方法.通用的方法写成一个个装饰器,这就为调用这些方法提供一个非常大的便利,如此提高我们代码的可读性以及简洁性,以及可扩展性. 在学习p ...

  9. (十)装饰器模式详解(与IO不解的情缘)

    作者:zuoxiaolong8810(左潇龙),转载请注明出处,特别说明:本博文来自博主原博客,为保证新博客中博文的完整性,特复制到此留存,如需转载请注明新博客地址即可. LZ到目前已经写了九个设计模 ...

随机推荐

  1. JAVA邀请码生成器

    code import java.util.Random; /** * 邀请码生成器,算法原理:<br/> * 1) 获取id: 1127738 <br/> * 2) 使用自定 ...

  2. 转:解决Onethink上传视频的问题 超棒的解决方案

    用过Onethink的都知道,它是不能上传视频的. 有人想到用上传附件的方式上传视频,但是结果……就是提示没有上传文件. 要是正常上传个一两兆的图片啊,压缩文件什么的还是可以的. 所以,重点来了 怎么 ...

  3. Poj 1182种类(带权)并查集

    题目链接 食物链 Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 44316 Accepted: 12934 Descriptio ...

  4. python中bisect模块的使用

    一般用于二分查找, 当然列表应该是有序表 参考于: http://blog.csdn.net/xiaocaiju/article/details/6975714

  5. 支付宝 python alipay 集成(转)

    即时到帐只是支付宝众多商家服务中的一个,表示客户付款,客户用支付宝付款,支付宝收到款项后,马上通知你,并且此笔款项与交易脱离关系,商家可以马上使用. 即时到帐只对企业客户服务,注册成功企业账号以后,申 ...

  6. js判断类型为数字的方法实现总汇——原生js判断isNumber()

    方法一[推荐]: 最容易想到的是用typeof来判断是否是number类型 ,但是如果为NaN会被认为也是number类型,因此我们需要使用isNaN来排除NaN的情况. function isNum ...

  7. arcgis 点线面操作

    <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title> ...

  8. HTML文档与盒子模型

    关于HTML 百度百科里是这么说的:超文本标记语言,即HTML(Hypertext Markup Language),是用于描述网页文档的一种标记语言. 为什么叫用于“描述”网页文档的“标记”语言呢? ...

  9. python编写购物车小程序

     #练习#程序购物车#启动程序后,让用户输入工资,  然后打印商品列表,允许用户根据商品编号购买商品用户选择商品后 #检测余额是否够,够就直接扣款,不够就提醒可随时退出,退出时,打印已购买商品和余额  ...

  10. 如何用最暴力的方法改写Liferay的原生portlet

    最近在论坛上看到有人问如何改写Liferay原有的calendar portlet. 然后研究了一下,直接从portal中把calendar portlet的源码拷贝出来,然后修改再部署上去,但是这个 ...