装饰器问题归纳
Posted rongze-blog
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了装饰器问题归纳相关的知识,希望对你有一定的参考价值。
1.什么是装饰器?
import time def timmer(func): start = time.time() func() end = time.time() print(end - start) # return end - start @timmer def foo(): time.sleep(3) print(‘hhh‘) foo #1 #执行结果: #hhh #3.0004751682281494
以上例子我们通过一个timmer装饰器希望计算foo函数的运行时间
整个过程其实可以理解为:一个函数的嵌套
即将foo函数嵌套入了timmer函数,类似于timmer(foo)
思考:但是为什么#1位置调用foo函数时不是使用foo()而是foo呢???
我们试一下
import time def timmer(func): start = time.time() func() end = time.time() print(end - start) # return end - start @timmer def 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 time def timmer(func): def inner(): start = time.time() func() end = time.time() print(end - start) return inner @timmer def foo(): time.sleep(3) print(‘hhh‘) foo() # 执行结果: # hhh # 3.000600576400757
得到了我们想要的结果
上面的修改给timmer函数的调用给一个inner返回值
所以执行timmer(foo)()时,就将timmer(foo)变为了一个可执行的函数
2.带有装饰器的函数有参数的情况
import time def timmer(func): def inner(i): start = time.time() func(i) end = time.time() print(end - start) return inner @timmer def foo(i): time.sleep(3) print(i) foo(‘hhh‘) # 执行结果: # hhh # 3.000600576400757
这里需要注意在foo函数的参数给装饰器传递时
并不是传递给了timmer函数,而是inner函数,类似于foo(i) == timmer(inner)(i) == inner(i)
3.装饰器带参数的情况
这种情况我们需要在装饰器外面再嵌套一个函数来专门接收装饰器传来的参数
import time def 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
以上是关于装饰器问题归纳的主要内容,如果未能解决你的问题,请参考以下文章