示例 7-15 定义了一个装饰器,它会在每次调用被装饰的函数时计时,然后把经过的时间、传入的参数和调用的结果打印出来。

示例 7-15 一个简单的装饰器,输出函数的运行时间

importtimedefclock(func):def clocked(*args): #➊

t0 =time.perf_counter()

result= func(*args) #➋

elapsed = time.perf_counter() -t0

name= func.__name__arg_str= ','.join(repr(arg) for arg inargs)print('[%0.8fs] %s(%s) -> %r' %(elapsed, name, arg_str, result))returnresultreturn clocked #➌

❶ 定义内部函数 clocked,它接受任意个定位参数。

❷ 这行代码可用,是因为 clocked 的闭包中包含自由变量 func。

❸ 返回内部函数,取代被装饰的函数。示例 7-16 演示了 clock 装饰器的用法。

示例 7-16 使用 clock 装饰器

#clockdeco_demo.py

importtimefrom clockdeco importclock

@clockdefsnooze(seconds):

time.sleep(seconds)

@clockdeffactorial(n):return 1 if n < 2 else n*factorial(n-1)if __name__=='__main__':print('*' * 40, 'Calling snooze(.123)')

snooze(.123)print('*' * 40, 'Calling factorial(6)')print('6! =', factorial(6))

运行示例 7-16 得到的输出如下:

$ python3 clockdeco_demo.py**************************************** Calling snooze(123)

[0.12405610s] snooze(.123) ->None**************************************** Calling factorial(6)

[0.00000191s] factorial(1) -> 1[0.00004911s] factorial(2) -> 2[0.00008488s] factorial(3) -> 6[0.00013208s] factorial(4) -> 24[0.00019193s] factorial(5) -> 120[0.00026107s] factorial(6) -> 720

6! = 720

工作原理

记得吗,如下代码

@clockdeffactorial(n):return 1 if n < 2 else n*factorial(n-1)

其实等价于:

deffactorial(n):return 1 if n < 2 else n*factorial(n-1)

factorial= clock(factorial)

因此,在两个示例中,factorial 会作为 func 参数传给 clock(参见示例 7-15)。然后, clock 函数会返回 clocked 函数,Python 解释器在背后会把 clocked 赋值给 factorial。

其实,导入clockdeco_demo 模块后查看 factorial 的 __name__ 属性,会得到如下结果:

>>> importclockdeco_demo>>> clockdeco_demo.factorial.__name__

'clocked'

>>>

所以,现在 factorial 保存的是 clocked 函数的引用。自此之后,每次调用 factorial(n),执行的都是 clocked(n)。clocked 大致做了下面几件事。

(1) 记录初始时间 t0。

(2) 调用原来的 factorial 函数,保存结果。

(3) 计算经过的时间。

(4) 格式化收集的数据,然后打印出来。

(5) 返回第 2 步保存的结果。

这是装饰器的典型行为:把被装饰的函数替换成新函数,二者接受相同的参数,而且(通常)返回被装饰的函数本该返回的值,同时还会做些额外操作。

示例 7-15 中实现的 clock 装饰器有几个缺点:不支持关键字参数,而且遮盖了被装饰函数的 __name__ 和 __doc__ 属性。示例 7-17 使用

functools.wraps 装饰器把相关的属性从 func 复制到 clocked 中。此外,这个新版还能正确处理关键字参数。

示例 7-17 改进后的 clock 装饰器

#clockdeco2.py

importtimeimportfunctoolsdefclock(func):

@functools.wraps(func)def clocked(*args, **kwargs):

t0=time.time()

result= func(*args, **kwargs)

elapsed= time.time() -t0

name= func.__name__arg_lst=[]ifargs:

arg_lst.append(','.join(repr(arg) for arg inargs))ifkwargs:

pairs= ['%s=%r' % (k, w) for k, w insorted(kwargs.items())]

arg_lst.append(','.join(pairs))

arg_str= ','.join(arg_lst)print('[%0.8fs] %s(%s) -> %r' %(elapsed, name, arg_str, result))returnresultreturn clocked

functools.wraps 只是标准库中拿来即用的装饰器之一。下一节将介绍 functools 模块中最让人印象深刻的两个装饰器:lru_cache 和singledispatch。

python3装饰器例子_python 装饰器(三):装饰器实例(一)相关推荐

  1. python常用的装饰器库_Python中的各种装饰器详解

    Python装饰器,分两部分,一是装饰器本身的定义,一是被装饰器对象的定义. 一.函数式装饰器:装饰器本身是一个函数. 1.装饰函数:被装饰对象是一个函数 [1]装饰器无参数: a.被装饰对象无参数: ...

  2. python判断密码是否正确三次机会_python密码错误三次锁定(实例讲解)

    程序需求: 输入用户名,密码 认证成功显示欢迎信息 输入错误三次后锁定用户 流程图: 好像画的不咋地 查看代码: #!/usr/bin/env python # _*_ coding:utf-8 _* ...

  3. python3装饰器例子_Python装饰器几个有用又好玩的例子

    装饰器是一种巧妙简洁的魔术,类似于Java中的面向切面编程,我们可以再函数执行前.执行后.抛出异常时做一些工作.利用装饰器,我们可以抽象出一些共同的逻辑,简化代码.而简化代码的同时,就是在增加代码鲁棒 ...

  4. python3闭包通俗解释_Python|闭包、装饰器,简单的实例,通俗的理解

    闭包和装饰器都是属于函数的语法范畴,是在函数定义中以另一个函数做为形参的语法机制. 1 闭包(Closurer) 闭包是定义内部函数的一种语法规则,要理解闭包,请看下面的实例:def outer(t) ...

  5. python二叉树遍历例子_python数据结构之二叉树的遍历实例

    遍历方案   从二叉树的递归定义可知,一棵非空的二叉树由根结点及左.右子树这三个基本部分组成.因此,在任一给定结点上,可以按某种次序执行三个操作: 1).访问结点本身(N) 2).遍历该结点的左子树( ...

  6. python for循环例子_Python for循环生成列表的实例

    Python for循环生成列表的实例 一般Python for语句前不加语句,但我在机器学习实战中看到了这两条语句: featList = [example[i] for example in da ...

  7. python中readlines函数例子_Python遍历方法readline()和readlines()实例讲解

    在进行Python项目开发(http://www.maiziedu.com/course/python/)中我们需要遍历一个大日志文件,在这个时候我们应该使用readlines()还是readline ...

  8. python 装饰器实现_Python装饰器系列01 - 如何正确地实现装饰器

    虽然人们能利用函数闭包(function clouser)写出简单的装饰器,但其可用范围常受限制.多数实现装饰器的基本方式会破坏与内省(Introspection)的关联性. 可大多数人会说:who ...

  9. python类装饰器应用_python之描述符应用与类的装饰器

    一.描述符应用 1.1上下文管理协议 在上文中我们提到with语句中的上下文管理器.with语句可以如此简单但强大,主要依赖于上下文管理器.那么什么是上下文管理器?上下文管理器就是实现了上下文协议的类 ...

最新文章

  1. 平安京服务器维护不能打字,《决战!平安京》:玩的真的累,我真的是服了这破游戏的举报系统...
  2. 干货!286页李宏毅《深度学习讲义》
  3. python列表排序方法-python list排序的两种方法及实例讲解
  4. 微软:Windows 7 和 10 都将删除自动更新!
  5. Java高级面试题!kafkastreams加时间窗口的count
  6. 如何建立大数据营销体系
  7. 二进制编辑和进程监控工具
  8. python博弈论代码_博弈论的算法总结
  9. 课程体系包括哪些要素_大数据课程体系和课程内容建设研究
  10. HTML中注解的写法正确的是,css注释的写法(单行和多行)
  11. Short Pairing-based Non-interactive Zero-Knowledge Arguments
  12. 141个关于人工智能的统计数据
  13. 门店数字化转型| 美容院管理系统
  14. HIT-哈工大数据结构-作业1(C++)
  15. Windows 源码编译 nginx (加入nginx-http-flv-module)
  16. JAVA泛型尖括号中的 T 和 ? 有什么区别?
  17. CAD梦想画图中的“线型设置”
  18. 瀑布 敏捷转换_敏捷的错觉(大多数敏捷转换最终实现了什么)
  19. 高德地图之反地理编码、线路规划、天气查询
  20. 《暗黑破坏神3》游戏拍卖行今日关闭

热门文章

  1. 使用Ajax解析数据遇到的问题
  2. WPF 带CheckBox、图标的TreeView
  3. Ubuntu apt-get 更新/查看软件
  4. 敏捷项目开源管理软件ScrumBasic(2)- 多项目支持
  5. redis watch multi exec 关系
  6. IOS开发之----常用函数和常数--秀清
  7. overfitting(过度拟合)的概念
  8. JavaScript URL参数读取
  9. 趁着对象泡脚的功夫,我把vueX吃透了
  10. freemarker常见语法大全