装饰器函数
什么是装饰器函数?
装饰器函数的本质就是闭包函数,也就是函数嵌套,内部函数调用外层函数变量
装饰器函数的功能
在不修改原函数以及调用方式的情况下,对原函数的功能进行扩展.
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
def warpper(func): def inner(): ret = func() return ret return inner @warpper #这里func1 = warpper(func1) 也就是inner() def func1() print('is ok!') func1() #被装饰器修饰过的函数在执行的步骤: 1.执行func1()的时候先执行warpper函数,同时将下面func1函数作为参数赋值func1() 2.这时warpper函数走完返回inner,inner=赋值后func1 3.func1() ==inner()调用内存函数 4.这时候走内存inner函数,内部调用下面func1()打印出 is ok
为什么要有装饰器函数?
因为我们在日常开发的过程中,不可能一次性将所有的应用功能全部实现,就算实现了以后也肯定会修改,所以我们必须允许代码可扩展,添加新功能,而装饰器函数恰好能够解决这一问题.在这种背景下,装饰器函数应用能够极大提高开发效率.
继续探索带参数的装饰器函数
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
import time def timer(func): def inner(num): start = time.time() func(num) print(time.time()-start) return inner @timer def func(num): print(num) func(1010) #输出 : 1010 0.0
通过查看上面代码发现装饰器函数没有返回值,没有返回值的函数可是缺乏灵魂的呢!
带参数有返回值的装饰器函数
#一个装饰器装饰多个函数
def warpper(func):
def inner(*args,**kwargs):
print('nice')
ret = func(*args,**kwargs)
print('bad')
return ret
return inner
@warpper
def func(*args,**kwargs):
print('The python is perfect!')
@warpper
def func1(*args,**kwargs):
print('The js is good!')
func()
func1()
#输出:
nice
The python is perfect!
bad
nice
The js is good!
bad
假如很多函数使用了一个装饰器,想要取消部分装饰器怎么办呢?
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
def outer(flag): def timer(func): def inner(*args,**kwargs): ret = func(*args, **kwargs) if flag: print(time.time()) return ret return inner return timer @outer(True) def func(): print('linux') func() #给装饰器再添加异常flag判断,当装饰器为False快速取消装饰器
多个装饰器装饰一个函数的效果
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
def warpper1(func): def inner(*args,**kwargs): print('w1情不知所起') ret = func(*args,**kwargs) print('w1一往而情深') return ret return inner def warpper2(func): def inner(*args,**kwargs): print('w2情不知所起') ret = func(*args,**kwargs) print('w2一往而情深') return ret return inner @warpper1 # func = warpper1(warpper2.inner) 此时的func是被warpper1.inner @warpper2 # func = warpper2(func) 此时的func是warpper2.inner def func(): print('You can you up!') func() #输出结果 w1情不知所起 w2情不知所起 You can you up! w2一往而情深 w1一往而情深 #执行步骤: 1.首先走wapper1.inner 因此首先打印'w1情不知所起', 2.往下执行,遇到ret = func()执行调用,此时调用的其实是warpper2.inner,因此跳转到warpper2的inner,打印出'w2情不知所起', 3.继续往下执行,再次遇到 ret = func().执行调用,此时调用的是原先的func函数,因此打印'You can you up!', 4.往下执行,打印'w2一往而情深', 5.由于warpper1函数并没有走完,因此回去再次往下执行,打印'w1一往而情深'.
装饰器的修复技术
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
示例1 from functools import wraps def ww(func): #@wraps(func) def inner(*args,**kwargs): ret = func(*args,**kwargs) return ret return inner @ww def func(): ''' 你好 :return: ''' pass func() print(func.__name__) print(func.__doc__) #输出结果 inner None 对比示例2 来看更加清晰 示例2 from functools import wraps def ww(func): @wraps(func) def inner(*args,**kwargs): ret = func(*args,**kwargs) return ret return inner @ww def func(): ''' 你好 :return: ''' pass func() print(func.__name__) print(func.__doc__) #输出 func 你好 :return: #由此看到添加@warps(func)后 被装饰过的func函数名称再调用的时候就是func了,也可以看到 func函数的注释等
总结:巧妙的运用装饰器函数是非常重要的
...