您的位置:首页 > 编程语言 > Python开发

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先装饰的是下面的makeItalictest函数在装饰这两个的时候将先运行下面的程序,即:

@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:这个代码实在是懒得再写一遍了

装饰器结束了!

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: