1.什么是装饰器?
import timedef timmer(func): start = time.time() func() end = time.time() print(end - start) # return end - start@timmerdef foo(): time.sleep(3) print('hhh') foo #1#执行结果:#hhh#3.0004751682281494
以上例子我们通过一个timmer装饰器希望计算foo函数的运行时间
整个过程其实可以理解为:一个函数的嵌套
即将foo函数嵌套入了timmer函数,类似于timmer(foo)
思考:但是为什么#1位置调用foo函数时不是使用foo()而是foo呢???
我们试一下
import timedef timmer(func): start = time.time() func() end = time.time() print(end - start) # return end - start@timmerdef foo(): time.sleep(3) print('hhh') foo()# 执行结果:# hhh# Traceback (most recent call last):# 3.000311851501465# File "E:/python/ftp_work/test.py", line 18, in <module># foo()# TypeError: 'NoneType' object is not callable
错误显示:'NoneType' object is not callable
原因是python装饰器设计在这一点上其实是不友好的
foo()相当于timmer(foo)(),而timmer(foo)()并不是一个可以运行的函数,因为timmer函数没有一个可执行的返回值
我们做如下修改
import timedef timmer(func): def inner(): start = time.time() func() end = time.time() print(end - start) return inner @timmerdef foo(): time.sleep(3) print('hhh') foo()# 执行结果:# hhh# 3.000600576400757
得到了我们想要的结果
上面的修改给timmer函数的调用给一个inner返回值
所以执行timmer(foo)()时,就将timmer(foo)变为了一个可执行的函数
2.带有装饰器的函数有参数的情况
import timedef timmer(func): def inner(i): start = time.time() func(i) end = time.time() print(end - start) return inner @timmerdef foo(i): time.sleep(3) print(i) foo('hhh')# 执行结果:# hhh# 3.000600576400757
这里需要注意在foo函数的参数给装饰器传递时
并不是传递给了timmer函数,而是inner函数,类似于foo(i) == timmer(inner)(i) == inner(i)
3.装饰器带参数的情况
这种情况我们需要在装饰器外面再嵌套一个函数来专门接收装饰器传来的参数
import timedef new_timmer(j): print(j) def timmer(func): def inner(i): start = time.time() func(i) end = time.time() print(end - start) return inner return timmer @new_timmer('xxx')def foo(i): time.sleep(3) print(i) foo('hhh')# 执行结果:# xxx# hhh# 3.0002424716949463
可以理解为foo(i) == new_timmer(j)()(i) == timmer(foo)(i) == inner(i)
参考:https://www.tuicool.com/articles/FBZvya
原文出处:https://www.cnblogs.com/Rongze-blog/p/9575285.html
共同學(xué)習(xí),寫下你的評(píng)論
評(píng)論加載中...
作者其他優(yōu)質(zhì)文章