python装饰器学习以及使用方法
2020-06-06 07:27
197 查看
装饰器学习
装饰器定义
装饰器原理
1、提出问题
def foo(): print('foo') pass #foo 表示的是函数 #foo() 表示的是执行foo函数
def foo(): print('foo') foo = lambda x:x+1 foo() #此时执行的是lambda表达式,而不是原来的foo函数,因为foo这个名字被重新指向了另外的一个匿名函数
在代码里面重名函数会覆盖后面的函数会覆盖前面定义的函数,导致原来定义的函数丢失,出现错误
2、实际问题
写代码要遵循开放封闭原则,虽然这个原则是用于面向对象开发的,但是也适用于函数式编程,简单来说,它规定已经实现功能代码是不允许修改的,但是可以被扩展。
TODO-封闭:已经实现的功能代码块
TODO-开放: 对扩展开放
伪代码 :
def w1(func): def inner(): #添加的功能一 #添加的功能二 #添加的功能三 func() return inner @w1 #语法糖 def f1(): print('f1') @w1 def f2(): print('f2') #此时w1作为额外的功能就被添加到各个需要添加的函数上了
对于上述代码,也是仅仅对基础平台代码进行修改,就可以实现在其他人调用函数f1,f2之前进行添加功能操作
实际的装饰器代码
def w1(func): def inner(): print('正在验证权限') func()#是为了在导入不同函数时,不发生冲突 return inner def f1(): print('---f1---') def f2(): print('---f2---') #innerFunction =w1(f1) #innerFunction() #但是此时使用的函数是innerFunction()不是原来的f1(),f2(),相当于改变了函数的调用方式 f1 =w1(f1) f1() #此时使用的是闭包对函数进行装饰,并且函数的调用方式未发生改变
两个装饰器
demo:
#定义函数完成包裹数据 def makeBold(fn): def wrapped(): return "<b>"+fn()+"</b>" return wrapped #定义函数完成包裹数据 def makeItalic(fn): def wrapped(): return "<i>"+fn()+"</i>" return wrapped @makeBold def test(): return "hello world__1" @makeItalic def test2(): return "hello world__2" @makeBold @makeItalic def test3(): return 'hello world__3' #在最后一个函数里面有两个装饰器 ret = test3() print(test1()) print(test2()) print(test3()) print(ret) #此时显示的是装饰顺序
其中makeBold先装饰的是下面的makeItalic和test函数在装饰这两个的时候将先运行下面的程序,即:
@makeItalic def test3(): print('---3---') return 'hello world' ret = test3() print(ret)
此时装饰器makeBold需要一个装饰一个函数,但是在此装饰器后面是另一个装饰器makeItalic在运行完这个装饰器后,才是一个函数,所以装饰器makeItalic会先运行,之后再由前面的装饰器装饰。
装饰器什么时候进行装饰
CODE:
def w1(func): print('---正在装饰---') def inner(): print('---正在验证权限---') func() return inner #只要python解释器执行到了这个代码,那就会自动的进行装饰,而不是等到调用的时候才装饰 @w1 def f1(): print('---f1---') #在调用函数之前,f1已经装饰完成 f1()
装饰器执行时间
第一个装饰器装饰前:
装饰器装饰后,传递的是装饰后的函数,给上一个装饰器
装饰器对有参数,无参数函数进行装饰
无参数函数
例子
from time import ctime,sleep def timefun(func): def wrappedfunc(): print('%s called at %s'%(func,__name__,ctime()) func() return wrappedfunc @timefun def foo(): print("i am foo") foo() sleep(2) foo()
两个参数函数
def func(functionName): print('---func---1---') def func_in(aa,bb): #如果不写出来形参,就会导致后面的调用失败这里不写参数就会导致,实际装饰多参数的函数时,实参传不进来 print('---func_in---1---') functionName(aa,bb)#此时的functionName是表示的后面被装饰的函数,如果不加实参在调用时,就会错误 #如果没有aa,bb当作实参传递就会导致最后调用失败 print('---func_in---2---') print('---func---2') return func_in @func def test(a,b): print('---test-a=%,b =%d---'%(a,b)) test(11,22)
多参数函数装饰
def func(functionName): print('---func---1---') def func_in(*args,**kwargs): #此时args是以 元组 保存,kwargs是以字典保存 print('---func_in---1---') functionName(*args,**kwargs)#此时的functionName是表示的后面被装饰的函数,如果不加实参在调用时,就会错误 #如果没有aa,bb当作实参传递就会导致最后调用失败 print('---func_in---2---') print('---func---2') return func_in @func def test(a,b): print('---test-a=%,b =%d---'%(a,b)) test(11,22) #当传递的实参数量不定时,可以设置多变量,如上所示,此时装饰的函数的实参数量不受限制
使用装饰器对有返回值的函数进行装饰
def func(functionName): print('---func---1---') def func_in(*args,**kwargs): print('func_in_begging') functionName(*args,**args) print('end of the func_in') print('decoration is over') return func_in @func def test(): print('what is your name') return 'haha' ret = test() print('test return value is %s'%ret) #此时打印的值是空值None理由如下
在装饰后,test现在指向的是func_in()函数,在后面对ret进行赋值,ret =test()时,赋值的是func_in这个函数,而func_in这个函数没有返回值,所以在输出的时候是None,
def func(functionName): print('---func---1---') def func_in(*args,**kwargs): print('func_in_begging') v= functionName(*args,**args) #此时的functionName接受到的值就是装饰的函数test返回的值,所以将这个值保存,并返回。 print('end of the func_in') return v print('decoration is over') return func_in @func def test(): print('what is your name') return 'haha' ret = test()#此时接受到的值才是真的需要返回的值 print('test return value is %s'%ret) #此时打印的值是空值None理由如下
通用的装饰器
式例模板
#通用的装饰器 #第一步:闭包 def w1(functionName): def w1_in(*args,**kwargs): #函数测试 return_key=functionName(*args,**kwargs) return return_key return w1_in @w1 def test(): print('test') @w1 def test1(): print('test1') return '测试' @w1 def test2(a,b,c): print(a,b,c)
带有参数的装饰器
OS:这个代码实在是懒得再写一遍了
装饰器结束了!
相关文章推荐
- Python学习23:函数装饰器的使用(方法重用)
- 基于python/opencv/tesseract使用传统方法的,表格图片版面分析以及印刷体汉字识别(持续更新,学习备份用)
- 黑马程序员——javascript语言的方法以及部分对象的使用学习日志
- Python学习之使用Future对象来异步返回结果方法详解
- Python中range的使用以及reverse List的方法
- “笨方法”学习Python笔记(2)-VS Code作为文本编辑器以及配置Python调试环境
- c#中类的学习以及使用方法
- Python进程池pool使用方法以及map函数用法
- Python学习5:__name__使用以及自定义模块
- 使用Python导出Excel图表以及到处为图片的方法
- Python学习笔记 --- 类中方法的使用
- 【Python学习系列十五】pandas库DataFrame行列操作使用方法
- [转] Python学习之Anaconda的使用及配置方法
- python中 pip的安装,更新,卸载模块以及使用方法
- 使用Python获取网段IP个数以及地址清单的方法
- 【Python3.6爬虫学习记录】(五)Cookie的使用以及简单的爬取知乎
- python使用装饰器和线程限制函数执行时间的方法
- scrapy一些非常实用资料整理,与其他mongdb、django、redis、solr、tor结合使用以及用Python脚本调用等等方法
- windows下安装python basemap时使用Visual Studio编译geos时遇到的问题以及解决方法