是什么:
首先,Python裝飾器的作用是:讓被裝飾的函數(shù)在不需要 任何 變化的情況下,增加額外的功能。
為什么:
為什么要用裝飾器呢,直接增加功能不就行了?
因為有的程序已經(jīng)上線或已經(jīng)被使用,那么就不能大批量的修改源代碼,于是就產(chǎn)生了裝飾器。
怎么裝飾:
預備知識:函數(shù)名和函數(shù)的區(qū)別,即帶括號和不帶括號的區(qū)別
1.test1表示的是函數(shù)的內(nèi)存 地址。 可以理解為一個指向某塊內(nèi)存的標簽。
2.test1()就是調(diào)用對在test1這個地址的內(nèi)容,即函數(shù)。
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
先執(zhí)行#1,test這個函數(shù)名傳給timer的func,此時,func就指向了test指向的地址塊了。
下面看timer()這個函數(shù)的結構:大盒子timer()里,有一個中盒子deco(),中盒子里有一個小盒子func(),小盒子是通過傳參傳入的。
接著看,大盒子的返回值是一個函數(shù)名,即大盒子返回的是中盒子的地址,此時timer()執(zhí)行完了,帶著返回值回到#1。
此時,test這個函數(shù)名,被賦值了中盒子deco的地址,也就是說,test指向了deco()這個函數(shù)的地址。
來捋一捋 ,剛才的中盒子deco()中嵌入了小盒子func(),也就是說,傳入的小盒子包在了中盒子deco()中。
經(jīng)過這個過程,test()函數(shù)指向了deco()函數(shù),【原本的功能包在了里邊,反過來說,test()的功能被擴展了。】
?
好,繼續(xù)剛才的代碼,#1執(zhí)行結束后,執(zhí)行#2,test()函數(shù)就找指向的位置,就找到了中盒子deco()的位置。
最后輸出什么呢?:NameError: name 'test' is not defined。
因為test的定義下載了下邊,執(zhí)行#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()本身有參數(shù)怎么寫?依葫蘆畫瓢吧。改動在#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、裝飾器帶參數(shù)
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后面跟了兩個括號。?這是什么意思??
其實很簡單,先執(zhí)行timer(‘ss’),返回結果為middl? ? 即 #7 處標注。?
再執(zhí)行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.
更多文章、技術交流、商務合作、聯(lián)系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號聯(lián)系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元
