python装饰器系列(三)

装饰器的应用实例

1 import time
2 def timeit(fn):
3     start = time.time()
4     fn()
5     print(time.time() - start)
6
7 def sleep():
8     time.sleep(3)

上边代码定义了两个函数,timeit函数能够模拟计算出在执行fn函数所花费的时间

1 timeit(sleep)
2 3.003638505935669

这样来计算一个函数的执行时间是有缺陷的,sleep函数必须是一个接收参数的函数,那怎样才能让sleep能接收参数呢?做如下改进:

 1 def timeit_1(fn):
 2     def wrap(x):
 3         start = time.time()
 4         fn(x)
 5         print(time.time() - start)
 6     return wrap
 7
 8
 9 def sleep_1(x):
10     time.sleep(x)
1 timeit_1(sleep_1)(3)
2 3.0035746097564697

这样timeit_1函数通过wrap函数进行一次包装后就可以让sleep函数接收一个参数,但如果sleep函数所接收的参数个数是不确定的呢?

这个可以采用python中的可变参数来解决,如下:

1 def timeit_2(fn):
2     def wrap(*args,**kwargs):
3         start = time.time()
4         fn(*args,**kwargs)
5         print(time.time() - start)
6     return wrap

这样对于sleep这个函数所需要接收的参数个数就没有限制了,调用方法与上边的不变

1 timeit_2(sleep_1)(3)
2 3.003852605819702

其实这里的timeit_2就是一个装饰器,在python中有一个语法糖来表示,如果在执行一个函数时,比如上边的sleep_1函数想在其执行前后增加一些语句操作,比如上边的start = time.time()print(time.time() - start),那在定义sleep_1函数时就可以加上一个装饰器来装饰此函数,这样定义的函数有其独特的语法,在定义函数时在其上边用一个@符号加上装饰器函数的名称即可

1 @timeit_2
2 def sleep_2(x):
3     time.sleep(x)

如上定义后的sleep_2的函数,我们在调用时就不需要再去调用timeit_2这个函数了,直接调用sleep_2函数即可,如下:

1 sleep_2(3)
2 3.0038673877716064

调用sleep_2(3)时,函数的执行流程:

首先把sleep_2函数作为参数传递到timeit_2这个装饰器函数中执行,返回一个wrap函数对象

再把调用sleep_2(3)函数时的参数3传递到wrap函数参数中进行函数调用,实质就是解释器会转换成timeit_2(sleep_2)(3)的方式来调用,

但是在已经使用@timeit_2语法来装饰函数sleep_2的场景下不能再使用timeit_2(sleep_2)(3)来调用函数,因为这样wrap函数会被执行两次。

总结一下:

装饰器的本质就是一个函数,此函数接收一个函数作为参数,返回一个函数,通常,返回的这个函数,是对传入的函数执行进行前后增加了一些语句,所以叫做装饰器。

原文地址:https://www.cnblogs.com/tianshug/p/10921830.html

时间: 2024-08-01 11:38:53

python装饰器系列(三)的相关文章

python装饰器系列(二)

对python装饰器系列(一)的deco函数进行修改: 1 def deco(fn): 2 def wrap(): 3 print('ha ha ha') 4 print('call {0} funtion'.format(fn.__name__)) 5 fn() 6 return wrap 1 @deco 2 def myfun(): 3 print('call myfun') 1 myfun() 2 3 ha ha ha 4 call myfun funtion 5 call myfun m

python装饰器系列(五)

带参数的装饰器的应用: 比如有一个函数,只有在对有许可权限的用户开放,执行此函数的用户没有在认证列表里的,就不会执行这个函数.这个该如何实现呢?如下: 1 def check(allow_users): 2 def inner_check(fn): 3 def wrap(username,*args,**kwargs): 4 '''This is wrap''' 5 if username in allow_users: 6 return fn(username,*args,**kwargs)

python装饰器系列(四)

带参数的装饰器 先来看一个不带参数的装饰器 1 import time 2 3 def timeit(fn): 4 def wrap(*args,**kwargs): 5 start = time.time() 6 ret = fn(*args,**kwargs) 7 print(time.time() - start) 8 return ret 9 return wrap 10 11 12 @timeit 13 def sleep(x): 14 time.sleep(x) 1 sleep(3)

Python装饰器、迭代器&生成器、re正则表达式、字符串格式化

Python装饰器.迭代器&生成器.re正则表达式.字符串格式化 本章内容: 装饰器 迭代器 & 生成器 re 正则表达式 字符串格式化 装饰器 装饰器是一个很著名的设计模式,经常被用于有切面需求的场景,较为经典的有插入日志.性能测试.事务处理等.装饰器是解决这类问题的绝佳设计,有了装饰器,我们就可以抽离出大量函数中与函数功能本身无关的雷同代码并继续重用.概括的讲,装饰器的作用就是为已经存在的对象添加额外的功能. 先定义一个基本的装饰器: ########## 基本装饰器 ########

5.初识python装饰器 高阶函数+闭包+函数嵌套=装饰器

一.什么是装饰器? 实际上装饰器就是个函数,这个函数可以为其他函数提供附加的功能. 装饰器在给其他函数添加功能时,不会修改原函数的源代码,不会修改原函数的调用方式. 高阶函数+函数嵌套+闭包 = 装饰器 1.1什么是高阶函数? 1.1.1函数接收的参数,包涵一个函数名. 1.1.2 函数的返回值是一个函数名. 其实这两个条件都很好满足,下面就是一个高阶函数的例子. def test1(): print "hamasaki ayumi" def test2(func): return t

Python装饰器与面向切面编程

今天来讨论一下装饰器.装饰器是一个很著名的设计模式,经常被用于有切面需求的场景,较为经典的有插入日志.性能测试.事务处理等.装饰器是解决这类问题的绝佳设计,有了装饰器,我们就可以抽离出大量函数中与函数功能本身无关的雷同代码并继续重用.概括的讲,装饰器的作用就是为已经存在的对象添加额外的功能. 1. 装饰器入门 1.1. 需求是怎么来的? 装饰器的定义很是抽象,我们来看一个小例子. 1 2 3 4 def foo():     print 'in foo()' foo() 这是一个很无聊的函数没错

Python装饰器由浅入深

装饰器的功能在很多语言中都有,名字也不尽相同,其实它体现的是一种设计模式,强调的是开放封闭原则,更多的用于后期功能升级而不是编写新的代码.装饰器不光能装饰函数,也能装饰其他的对象,比如类,但通常,我们以装饰函数为例子介绍其用法.要理解在Python中装饰器的原理,需要一步一步来.本文尽量描述得浅显易懂,从最基础的内容讲起. (注:以下使用Python3.5.1环境) 一.Python的函数相关基础 第一,必须强调的是python是从上往下顺序执行的,而且碰到函数的定义代码块是不会立即执行它的,只

【转】九步学习python装饰器

本篇日志来自:http://www.cnblogs.com/rhcad/archive/2011/12/21/2295507.html 纯转,只字未改.只是为了学习一下装饰器.其实现在也是没有太看明白,对于装饰器我就是用的时候找例子,能蒙对,但是用过之后一段时间就忘了.还是用的少.有空应该好好看一看的,包括闭包.对于各种现代编程语言来说闭包都是很重要的.在这里先谢过原作者,如有侵权请告知. =-=-=-=-=-=-=-=-=-=-一条不怎么华丽的分隔线-=-=-=-=-=-=-=-=-=-= 这

【Python之旅】第四篇(一):Python装饰器

有时候拿到一个程序接口,需要对其进行扩展,但是又不能修改原来接口的源代码,这时候就需要使用装饰器了. 有下面一个小程序,假如是别人提供给我们的调用接口: import time def sayHi():         time.sleep(1)         print 'Hello, I am xpleaf.' 一般情况下,如果想要计算该程序的执行时间(因为有可能要对该接口进行某些性能上的测试),就需要把以上接口修改为下面这样,同时执行一下: 程序代码: import time def s