赞
踩
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:这个代码实在是懒得再写一遍了
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。