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.lang.ClassCastException: java.io.ByteArrayInputStream cannot be cast to java.io.FileInputStream

    今天在做文件上传的时候遇到一个这样的问题 java.lang.ClassCastException: java.io.ByteArrayInputStream cannot be cast to ja ...

  2. 上传同步github

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

  3. Laravel(PHP)使用Swagger生成API文档不完全指南 - 基本概念和环境搭建 - 简书

    在PHPer中,很多人听说过Swagger,部分人知道Swagger是用来做API文档的,然而只有少数人真正知道怎么正确使用Swagger,因为PHP界和Swagger相关的资料实在是太少了.所以鄙人 ...

  4. Data Visualisation Cheet Sheet

    Univariate plotting with pandas import pandas as pd reviews = pd.read_csv() reviews.head() //bar rev ...

  5. 官方支持的全新版Neo4j-JDBC驱动3.0

    原文:The All-New, Officially Supported Neo4j-JDBC Driver 3.0 作者: Michael Hunger 译者:仲培艺,关注数据库领域,纠错.寻求报道 ...

  6. Python数据分析与展示[第一周]

    ipython 中的问号 获得相关的描述信息 %run 系统文件 执行某一个文件 ipython的模式命令 %magic 显示所有的魔术命令 %hist    命令历史输入信息 %pdb    异常发 ...

  7. iOS音频篇:使用AVPlayer播放网络音乐

    http://www.cocoachina.com/ios/20160324/15767.html 引言 假如你现在打算做一个类似百度音乐.豆瓣电台的在线音乐类APP,你会怎样做? 首先了解一下音频播 ...

  8. PHP定时任务获取微信access_token的方法

    一.使用brew安装php多版本方法 # brew install php56# brew install php70二.安装切换工具 # brew install php-version# sour ...

  9. CentOS下重启uwsgi

    使用Django开发项目,每次修改内容无法刷新,重启nginx也无效,每次都重启主机, 网上搜索很多资料,发现可以重启uwsgi来解决问题,但是发现uwsgi重启每个人都不一样,很多人写了脚本重启 我 ...

  10. 如何合并两个git commit

    把你的修改stage之后运行: git rebase -i HEAD~2 然后把第二行的pick改成squash就ok啦 note: 同理,如果要合并多个commit,把后面的2改成你想要合并的com ...