day11 python之函数装饰器
一,什么是装饰器?
装饰器本质上就是一个python函数,他可以让其他函数在不需要做任何代码变动的前提下,增加额外的功能,装饰器的返回值也是一个函数对象。
装饰器的应用场景:比如插入日志,性能测试,事务处理,缓存等等场景。
二,装饰器的形成过程。
现在我有一个需求,我想让你测试这个函数的执行时间,在不改变这个函数代码的情况下:
import time def func1():
print('in func1') def timer(func):
start = time.time()
func()
print(time.time() - start) timer(func1)
上面的代码输出了func1()函数的运行时间,但是我们计算func1()函数的运行时间时,需要调用的是timer(func)函数
有没有办法直接调用func1()函数就能计算func1()函数运行时间呢?
如果让 func1 = timer 呢? 可是timer()函数需要一个函数参数,而我们的 func1 是不需要参数的,显然不行
那该怎么实现呢? 换个思路, timer不能赋值给func1,但是我们可以给timer指定一个函数返回值,将他赋值给func1
那么执行 func1() 时就相当于执行 这个用来赋值的函数.而这个函数在timer()函数内,可以调用timer()函数的参数func
如下所以,我们使用闭包的方法解决了这个问题
import time # 引入时间模块 def func1(): # 要测试执行时间的函数
print('in func1') def timer(func):
def inner():
start = time.time()
func()
print(time.time() - start)
return inner func1 = timer(func1) # time()的返回值是inner
func1() # func1()==inner()
在上面的方法中,timer()函数就是我们的装饰器函数,func1()是被装饰的.
但是,在上面的例子中,func1()是没有返回值和参数的,要是带上参数返回值呢?
import time # 引入时间模块 def func1(a,b=1): # 要测试执行时间的函数
print('in func1')
return 'func1的返回值' def timer(func):
def inner(*args,**kwargs): # 设置为可以接受任意参数
start = time.time()
set = func(*args,**kwargs)
print(time.time() - start)
return set # 返回func函数原本的返回值
return inner func1 = timer(func1) # time()的返回值是inner
func1(a,b=3) # func1(a,b=3)==inner(a,b=3)
但是如果有多个函数,我都想让你测试他们的执行时间,你每次是不是都得func1 = timer(func1)?这样还是有点麻烦,因为这些函数的函数名可能是不相同,有func1,func2,graph,等等,所以更简单的方法,python给你提供了,那就是语法糖。
@timer # == func1 = timer(func1)
上面的装饰器已经非常完美了,但是有我们正常情况下查看函数信息的方法在此处都会失效:
def index():
'''这是一个主页信息'''
print('from index') print(index.__doc__) #查看函数注释的方法
print(index.__name__) #查看函数名的方法
如何解决这个问题呢?
from functools import wraps def deco(func):
@wraps(func) #加在最内层函数正上方
def wrapper(*args,**kwargs):
return func(*args,**kwargs)
return wrapper @deco
def index():
'''哈哈哈哈'''
print('from index') print(index.__doc__)
print(index.__name__)
三,开放封闭原则。
1.对扩展是开放的
为什么要对扩展开放呢?
我们说,任何一个程序,不可能在设计之初就已经想好了所有的功能并且未来不做任何更新和修改。所以我们必须允许代码扩展、添加新功能。
2.对修改是封闭的
为什么要对修改封闭呢?
就像我们刚刚提到的,因为我们写的一个函数,很有可能已经交付给其他人使用了,如果这个时候我们对其进行了修改,很有可能影响其他已经在使用该函数的用户。
装饰器完美的遵循了这个开放封闭原则。
四,装饰器的主要功能和固定结构。
def timer(func):
def inner(*args,**kwargs):
'''执行函数之前要做的'''
re = func(*args,**kwargs)
'''执行函数之后要做的'''
return re
return inner
from functools import wraps def deco(func):
@wraps(func) #加在最内层函数正上方,确保查看函数信息的方法可用
def wrapper(*args,**kwargs):
'''执行函数之前要做的'''
re = func(*args,**kwargs)
'''执行函数之后要做的'''
return re
return wrapper
装饰器的固定格式--wraps版
五,带参数的装饰器。
注意@outer(False)的用法
上面的@timer 相当于 func = timer(func) , 返回值是 inner
下面的@outer(False) 相当于 func = outer(False)(func) ,返回值仍是 inner
def outer(flag):
def timer(func):
def inner(*args,**kwargs):
if flag:
print('''执行函数之前要做的''')
re = func(*args,**kwargs)
if flag:
print('''执行函数之后要做的''')
return re
return inner
return timer @outer(False) #此处相较上面的语法糖,多了括号和参数.@outer(False)==>func=outer(False)(func),返回值仍是inner
def func():
print(111) func()
六,多个装饰器装饰一个函数。
def wrapper1(func):
def inner():
print('wrapper1 ,before func')
func()
print('wrapper1 ,after func')
return inner def wrapper2(func):
def inner():
print('wrapper2 ,before func')
func()
print('wrapper2 ,after func')
return inner @wrapper2
@wrapper1
def f():
print('in f') f()
day11 python之函数装饰器的更多相关文章
- python基础—函数装饰器
python基础-函数装饰器 1.什么是装饰器 装饰器本质上是一个python函数,它可以让其他函数在不需要做任何代码变动的前提下增加额外功能. 装饰器的返回值是也是一个函数对象. 装饰器经常用于有切 ...
- Day11 Python基础之装饰器(高级函数)(九)
在python中,装饰器.生成器和迭代器是特别重要的高级函数 https://www.cnblogs.com/yuanchenqi/articles/5830025.html 装饰器 1.如果说装 ...
- python基础-----函数/装饰器
函数 在Python中,定义一个函数要使用def语句,依次写出函数名.括号.括号中的参数和冒号:,然后,在缩进块中编写函数体,函数的返回值用return语句返回. 函数的优点之一是,可以将代码块与主程 ...
- Decorator——Python初级函数装饰器
最近想整一整数据分析,在看一本关于数据分析的书中提到了(1)if __name__ == '__main__' (2)列表解析式 (3)装饰器. 先简单描述一下前两点,再详细解说Python初级的函数 ...
- python 复习函数 装饰器
# 函数 —— 2天 # 函数的定义和调用 # def 函数名(形参): #函数体 #return 返回值 #调用 函数名(实参) # 站在形参的角度上 : 位置参数,*args,默认参数(陷阱),* ...
- python 匿名函数&装饰器
匿名函数 关键字lambda表示匿名函数,冒号前面的x表示函数参数匿名函数有个限制,就是只能有一个表达式,不用写return,返回值就是该表达式的结果. >>> list(map(l ...
- python闭包函数&装饰器
一.函数引用 函数可以被引用 函数可以被赋值给一个变量 def hogwarts(): print("hogwarts") # hogwarts() # 函数调用 print(ho ...
- Python之函数装饰器
在实际中,我们可能需要在不改变函数源代码和调用方式的情况下,为函数添加一些新的附加功能,能够实现这种功能的函数我们将其称之为装饰器.装饰器本质上其实还是是一个函数,用来装饰其它函数,为函数添加一些附加 ...
- python 之 函数 装饰器
5.8 装饰器 1 开放封闭原则 软件一旦上线后,就应该遵循开放封闭原则,即对修改源代码是封闭的,对功能的扩展是开放的 也就是说我们必须找到一种解决方案: 能够在不修改一个功能源代码以及调用方式的前提 ...
随机推荐
- Java中Comparable和Comparator区别
很好的一篇博客:http://blog.csdn.net/jq_ak47/article/details/61203817 http://www.cnblogs.com/cmxwt/p/6215253 ...
- SAP Parallel Accounting(平行分类账)业务配置及操作手册
目录 SAP Parallel Accounting(平行分类账业务)配置及操作手册 SAP Parallel Accounting(平行分类账业务)配置及操作手册 Overview 业务说明 为了适 ...
- VMware vCenter Server 6.5配置群集功能
虚拟数据中心是一种容器,其中包含用于操作虚拟机的完整功能环境所需要的全部清单对象.可以创建多个数据中心,以实际需求创建 . 群集是一组主机,将主机添加到群集时,主机的资源将成为群集资源的一部分,群集管 ...
- 运营商挂时长神器,批量导入账号,导出账号状态,随机修改MAC地址
话不多说,直接上图 可批量导入账号,同时修改广域网口MAC地址 导出账号状态,包括在线时长,MAC,IP地址等等
- ajax-page局部刷新分页实例
1.引用文件:connect.php <?php $host="localhost"; $db_user="root"; $db_pass="r ...
- PHP memcached memcache 扩展安装
好久没配置环境今天安装PHP 开发环境, 项目比较老,一开始以为项目用的是memcache 装完后发现 项目用的是memcached 所以正好两个都装了. 碰到些坑希望能帮助到百度到这篇文章的伙伴 . ...
- pytest 3.9在python 2.7下的一个bug
最在在使用pytest,用的是pytest 3.9.3,python版本为2.7.10,但一直在使用时发现总提示 File "c:\python27\Lib\json\__init__.py ...
- 对unicode数据进行部分replace
unicode = u'\u9879\u76ee\u7ba1\u7406\u90e8' print unicode #项目管理部 unicode = unicode.replace("项目& ...
- E - Heavy Transportation
来源poj1797 Background Hugo Heavy is happy. After the breakdown of the Cargolifter project he can now ...
- poj 2074
哎怎么说,感觉现在处理平面上点线的题已经比较熟练了. 这题就离散化然后搞个前缀和就没了. 准备开始进一步的自闭了. 下面是disguss的一些样例... 其实是我自己写错了个地方,本来能1A的. #i ...