# -*-coding=utf-8 -*-
#实现一个函数执行后计算执行时间的功能
__author__ = 'piay'
import time, functools def foo():
'''
定义一个普通函数
:return:
'''
print 'this is foo' foo() '''
这里如果我们需要查看函数执行时间,修改为:
''' def foo1():
start_time = time.clock()
print 'this is foo1'
end_time = time.clock()
print '执行时间为:', end_time - start_time foo1() '''
如果我们其他的函数也需要执行时间,或者这个函数不需要执行时间,那么我们就需要复制到其他的函数中去
这是一种最差的方法
''' def foo3():
print 'this is foo3' def timeit(func):
'''
我们可以考虑重新定义一个函数timeit,将foo的引用传递给他,
然后在timeit中调用foo并进行计时,这样,我们就达到了不改动foo定义的目的
:param func: 传入的函数
:return:
'''
start_time = time.clock()
func()
end_time = time.clock()
print 'used:', end_time - start_time timeit(foo3)
'''
这样写修改调用部分的代码。原本我们是这样调用的:foo3(),现在变成timeit(foo),这样的话,如果foo在N处都被调用了,
你就不得不去修改这N处的代码。或者更极端的,考虑其中某处调用的代码无法修改这个情况,比如:这个函数是你交给别人使用的。
''' '''
想想办法不修改调用的代码;如果不修改调用代码,也就意味着调用foo()需要产生调用timeit(foo)的效果。我们可以想到将timeit赋值给foo,
但是timeit似乎带有一个参数……想办法把参数统一吧!如果timeit(foo)不是直接产生调用效果,
而是返回一个与foo参数列表一致的函数的话……就很好办了,将timeit(foo)的返回值赋值给foo,然后,调用foo()的代码完全不用修改!
''' def foo4():
print 'this is foo4' # 定义一个计时器,传入一个,并返回另一个附加了计时功能的方法
def timeit4(func):
# 定义一个内嵌的包装函数,给传入的函数加上计时功能的包装
def wrapper():
start_time = time.clock()
func()
end_time = time.clock()
print 'used:', end_time - start_time # 将包装后的函数返回
return wrapper foo_1 = timeit(foo4)
'''
上面的代码就类似装饰器了,可以修改为如下:
''' @timeit4 # 定义上加上这一行与另外写foo = timeit(foo)完全等价
def foo5():
print 'this is foo5'
foo5() '''
-----------------------------------------------
使用functools.wraps(func)装饰器实现功能
'''
def timeit_3_for_wraps(func):
@functools.wraps(func)
def wrapper():
start=time.clock()
func()
end=time.clock()
print 'used:',end-start
return wrapper @timeit_3_for_wraps
def foo6():
print 'this is foo6'
foo6()

这里实现一个完整的判断是否带参数的装饰器:

# -*-coding=utf-8 -*-
__author__ = 'piay'
import functools, time
'''
一个函数执行前打印开始执行,执行完后打印执行完成,记录执行时间
''' def log(text):
if callable(text): # 参数如果是函数,说明装饰器不带参传过来,text是一个函数
@functools.wraps(text)
def wrapper(*args, **kwargs):
start = time.clock()
print '这是不带参数的装饰器,开始执行'
f = text(*args, **kwargs) #执行本身的函数 text()
end = time.clock()
print "结束执行:", end - start
return f # 返还原函数
return wrapper elif not callable(text): # text是参数,不是函数
def decarator(func):
@functools.wraps(func)
def warpper(*args, **kwargs):
start = time.clock()
print '这是不带参数的装饰器,开始执行,参数为:'+text
f = func(*args, **kwargs)
end=time.clock()
print "结束执行:",end-start
return f #返还原函数
return warpper
return decarator
else:
print '请检查是否正确' @log
def add1(x,y):
print x+y @log('')
def add2(x,y):
print x+y add1(1,2)
add2(2,3)

执行结果:

D:\Python27\python.exe D:/Python/functools_study/完整的装饰器.py
这是不带参数的装饰器,开始执行
3
结束执行: 5.08444509009e-05
这是不带参数的装饰器,开始执行,参数为:222
5
结束执行: 2.49333364995e-05

Process finished with exit code 0

python functools.wraps装饰器模块的更多相关文章

  1. python中functools.wraps装饰器的作用

    functools.wraps装饰器用于显示被包裹的函数的名称 import functools def node(func): #@functools.wraps(func) def wrapped ...

  2. 探究functools模块wraps装饰器的用途

    <A Byte of Python>17.8节讲decorator的时候,用到了functools模块中的一个装饰器:wraps.因为之前没有接触过这个装饰器,所以特地研究了一下. 何谓“ ...

  3. 关于functools模块的wraps装饰器用途

    测试环境:Python3.6.2 + win10 +  Pycharm2017.3 装饰器之functools模块的wraps的用途: 首先我们先写一个装饰器 # 探索functools模块wraps ...

  4. Python 中实现装饰器时使用 @functools.wraps 的理由

    Python 中使用装饰器对在运行期对函数进行一些外部功能的扩展.但是在使用过程中,由于装饰器的加入导致解释器认为函数本身发生了改变,在某些情况下——比如测试时——会导致一些问题.Python 通过  ...

  5. python学习笔记2-functools.wraps 装饰器

    wraps其实没有实际的大用处, 就是用来解决装饰器导致的原函数名指向的函数 的属性发生变化的问题: 装饰器装饰过函数func, 此时func不是指向真正的func,而是指向装饰器中的装饰过的函数 i ...

  6. python高级之装饰器

    python高级之装饰器 本节内容 高阶函数 嵌套函数及闭包 装饰器 装饰器带参数 装饰器的嵌套 functools.wraps模块 递归函数被装饰 1.高阶函数 高阶函数的定义: 满足下面两个条件之 ...

  7. Day04 - Python 迭代器、装饰器、软件开发规范

    1. 列表生成式 实现对列表中每个数值都加一 第一种,使用for循环,取列表中的值,值加一后,添加到一空列表中,并将新列表赋值给原列表 >>> a = [0, 1, 2, 3, 4, ...

  8. 第二篇:python高级之装饰器

    python高级之装饰器   python高级之装饰器 本节内容 高阶函数 嵌套函数及闭包 装饰器 装饰器带参数 装饰器的嵌套 functools.wraps模块 递归函数被装饰 1.高阶函数 高阶函 ...

  9. Python 中的装饰器

    说到装饰器是我们每个学Python人中的心痛. 装饰器作用:是用来装饰其他函数的,为其他函数添加新功能. 原则:1.不能改变被修饰函数的源代码. 2.不能修改被修饰函数的调用方式. 学装饰器前还需要了 ...

随机推荐

  1. 一个oracle存储过程

    打开plsql,在packages文件夹里新建存储过程 在sql窗口中运行如下语句 create or replace package SY_USER_PKG1 is TYPE MYCURSOR IS ...

  2. QT 串口通信 数据16进制发送

    在QT中进行串口通信时,很多情况要用到发送16进制的数据.从网上找来了一段代码测试能用: static QByteArray QString2Hex(QString str) { QByteArray ...

  3. 批处理SQL语句

    作用:想发送多条SQL,又要降低与数据库系统的交互,这时使用批处理        一]Statement对象——适合对不同结构的SQL语句进行批处理操作        步骤:            1 ...

  4. Qt事件机制浅析(定义,产生,异步事件循环,转发,与信号的区别。感觉QT事件与Delphi的事件一致,而信号则与Windows消息一致)

    Qt事件机制 Qt程序是事件驱动的, 程序的每个动作都是由幕后某个事件所触发.. Qt事件的发生和处理成为程序运行的主线,存在于程序整个生命周期. Qt事件的类型很多, 常见的qt的事件如下: 键盘事 ...

  5. AzCopy – 跨帐户复制 Blob

    您可以随时从 aka.ms/AzCopy 下载最新版本. 去年4月发布的版本中的新增功能 支持跨帐户复制 Blob:AzCopy 允许您在相同存储帐户内或不同存储帐户之间复制 Blob(有关跨帐户 B ...

  6. poj3254:基础状压dp

    第二个状压dp 做过的第一个也是放牛问题,两头牛不能相邻 这个题多了一个限制,就是有些位置不能放牛 于是先与处理一下每一行所有不能放牛的状态,处理的过程直接对每一个不能放牛的状态或以下 ac代码: # ...

  7. 【案例】舒邑:一个女装品牌的奇葩打法-@i黑马

    [案例]舒邑:一个女装品牌的奇葩打法-@i黑马 [案例]舒邑:一个女装品牌的奇葩打法

  8. 【转】AAC ADTS格式分析

    1.ADTS是个啥 ADTS全称是(Audio Data Transport Stream),是AAC的一种十分常见的传输格式. 记得第一次做demux的时候,把AAC音频的ES流从FLV封装格式中抽 ...

  9. 编程之美2015初赛第一场 hihoCoder #1156 : 彩色的树(染色问题)

    #1156 : 彩色的树 时间限制:2000ms 单点时限:1000ms 内存限制:256MB 描述 给定一棵n个节点的树,节点编号为1, , …, n.树中有n - 1条边,任意两个节点间恰好有一条 ...

  10. 工作中用到的linux命令

    都是工作中用到的,解决问题至上,不求甚解,怕再忘了,所以记录一下,勿喷. .log |,,,,|,| 先说一下这条命令: cat:打印文件内容 grep:查找,用到的有\s匹配空白字符 sed:刚用到 ...