是什么:
首先,Python装饰器的作用是:让被装饰的函数在不需要 任何 变化的情况下,增加额外的功能。
为什么:
为什么要用装饰器呢,直接增加功能不就行了?
因为有的程序已经上线或已经被使用,那么就不能大批量的修改源代码,于是就产生了装饰器。
怎么装饰:
预备知识:函数名和函数的区别,即带括号和不带括号的区别
1.test1表示的是函数的内存 地址。 可以理解为一个指向某块内存的标签。
2.test1()就是调用对在test1这个地址的内容,即函数。
3.再通俗的比喻,test1是存折,test1()才是你的钱。
看个半成品代码:
import time
def timer(func):
def deco():
start = time.time()
func()
stop = time.time()
print(stop-start)
return deco
test = timer(test) #1
def test():
time.sleep(2)
print("test is running!")
test() #2
先执行#1,test这个函数名传给timer的func,此时,func就指向了test指向的地址块了。
下面看timer()这个函数的结构:大盒子timer()里,有一个中盒子deco(),中盒子里有一个小盒子func(),小盒子是通过传参传入的。
接着看,大盒子的返回值是一个函数名,即大盒子返回的是中盒子的地址,此时timer()执行完了,带着返回值回到#1。
此时,test这个函数名,被赋值了中盒子deco的地址,也就是说,test指向了deco()这个函数的地址。
来捋一捋 ,刚才的中盒子deco()中嵌入了小盒子func(),也就是说,传入的小盒子包在了中盒子deco()中。
经过这个过程,test()函数指向了deco()函数,【原本的功能包在了里边,反过来说,test()的功能被扩展了。】
好,继续刚才的代码,#1执行结束后,执行#2,test()函数就找指向的位置,就找到了中盒子deco()的位置。
最后输出什么呢?:NameError: name 'test' is not defined。
因为test的定义下载了下边,执行#1的时候就找不到他的定义。因此把test()的定义挪到#1上边就行了。
(这么看来,两个也不是完全等价)
就会输出:
test is running!
2.000791072845459
成品代码:
1、我们见到的装饰器装什么样子呢?
import time
def timer(func):
def deco():
start = time.time()
func()
stop = time.time()
print(stop-start)
return deco
@timer
def test():
time.sleep(2)
print("test is running!")
test() #2
把test = timer(test)替换成@timer 放在def test():的上边。
2、如果test()本身有参数怎么写?依葫芦画瓢吧。改动在#3、#4、#5.
import time
def timer(func):
def deco(*args, **kwargs): #3
start = time.time()
func(*args, **kwargs) #4
stop = time.time()
print(stop-start)
return deco
@timer
def test(parameter): #5
time.sleep(2)
print("test is running!")
test()
3、装饰器带参数
import time
def timer(p): #7
def middl(func): #8
def deco(*args, **kwargs):
if p == 'ss':
start = time.time()
res = func(*args, **kwargs)
stop = time.time()
print(stop-start)
return res
return deco #8
return middl #7
@timer('ss')
def test(): #8
time.sleep(2)
print("test is running!")
test()
就在timer()和deco()中间在套一层middl()。
此时@timer(’ss')相当于:test = timer('ss')(test )
注意!这里timer后面跟了两个括号。 这是什么意思?
其实很简单,先执行timer(‘ss’),返回结果为middl 即 #7 处标注。
再执行middl(test),得到的返回结果为deco 即 #8 处标注。
参考1:https://blog.csdn.net/weixin_39541558/article/details/79972104
参考2:https://blog.csdn.net/buster_zr/article/details/81104551
The end.