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. Vue.之.创建项目

    Vue.之.创建项目 第一次使用vue的时候,在已完成node的情况下,还需要在进行安装vue. 指令:cnpm install vue-cli -g      //全局安装 vue-cli 检查vu ...

  2. css不定高图文垂直居中的三种方法

    html部分 <div class="box"> <img class="img" src="http://p2.so.qhmsg. ...

  3. 上传同步github

    …or create a new repository on the command line   echo "# testproject" >> README.md ...

  4. 启动Hadoop时,DataNode启动后一会儿自动消失的解决方法

    查看slaver1/2的logs,发现 FATAL org.apache.hadoop.hdfs.server.datanode.DataNode: Initialization failed for ...

  5. jeecg Access restriction 问题解决

    最近导入新项目,导入所有用到的jar包,发现其中一个引用报错 import com.sun.istack.internal.Nullable; 具体信息如下: Access restriction: ...

  6. AutoDesk产品,Maya 2018 安装,Microsoft Visual C++ 2012 安装失败,结果 = -2147024546,安装Microsoft Visual C++ 2012 Redistributable 错误0x80070005 等等

    今日老弟装Maya 2018出现问题,我帮忙解决了一下问题,过程颇为曲折,记录一下,看能否帮到有类似困惑的朋友. 我和老弟的电脑牌子一样,就现在自己电脑上装了,竟然开始和他的错误是一样的!都是Micr ...

  7. C++通配符

    #include<iostream>using namespace std;bool PathernMatch(char *pat, char *str){ char *s = NULL; ...

  8. iOS自动化打包上传的踩坑记

    http://www.cocoachina.com/ios/20160624/16811.html 很久以前就看了很多关于iOS自动打包ipa的文章, 看着感觉很简单, 但是因为一直没有AppleDe ...

  9. kubernetes1.5新特性跟踪(续)

    Kubernetes发布历史回顾 Kubernetes 1.0 - 2015年7月发布 Kubernetes 1.1 - 2015年11月发布 Kubernetes 1.2 - 2016年3月发布 K ...

  10. java memory allocation(转)

    Java的运行时数据存储机制 Java程序在运行时需要为一系列的值或者对象分配内存,这些值都存在什么地方?用什么样的数据结构存储?这些数据结构有什么特点?本文试图说明此命题的皮毛之皮毛. 概念   对 ...