您好,登錄后才能下訂單哦!
今天小編給大家分享的是python裝飾器帶參數(shù)的使用方式,相信很多人都不太了解,為了讓大家更加了解python裝飾器,所以給大家總結(jié)了以下內(nèi)容,一起往下看吧。一定會(huì)有所收獲的哦。
python裝飾器詳解
python裝飾器的詳細(xì)解析
什么是裝飾器?
python裝飾器(fuctional decorators)就是用于拓展原來(lái)函數(shù)功能的一種函數(shù),目的是在不改變?cè)瘮?shù)名(或類名)的情況下,給函數(shù)增加新的功能。
這個(gè)函數(shù)的特殊之處在于它的返回值也是一個(gè)函數(shù),這個(gè)函數(shù)是內(nèi)嵌“原“”函數(shù)的函數(shù)。
一般而言,我們要想拓展原來(lái)函數(shù)代碼,最直接的辦法就是侵入代碼里面修改,例如:
import time def f(): print("hello") time.sleep(1) print("world")
這是我們最原始的的一個(gè)函數(shù),然后我們?cè)噲D記錄下這個(gè)函數(shù)執(zhí)行的總時(shí)間,那最簡(jiǎn)單的做法就是改動(dòng)原來(lái)的代碼:
import time def f(): start_time = time.time() print("hello") time.sleep(1) print("world") end_time = time.time() execution_time = (end_time - start_time)*1000 print("time is %d ms" %execution_time)
但是實(shí)際工作中,有些時(shí)候核心代碼并不可以直接去改,所以在不改動(dòng)原代碼的情況下,我們可以再定義一個(gè)函數(shù)。(但是生效需要再次執(zhí)行函數(shù))
import time def deco(func): start_time = time.time() f() end_time = time.time() execution_time = (end_time - start_time)*1000 print("time is %d ms" %execution_time) def f(): print("hello") time.sleep(1) print("world") if __name__ == '__main__': deco(f) print("f.__name__ is",f.__name__) print()
這里我們定義了一個(gè)函數(shù)deco,它的參數(shù)是一個(gè)函數(shù),然后給這個(gè)函數(shù)嵌入了計(jì)時(shí)功能。但是想要拓展這一千萬(wàn)個(gè)函數(shù)功能,
就是要執(zhí)行一千萬(wàn)次deco()函數(shù),所以這樣并不理想!接下來(lái),我們可以試著用裝飾器來(lái)實(shí)現(xiàn),先看看裝飾器最原始的面貌。
import time def deco(f): def wrapper(): start_time = time.time() f() end_time = time.time() execution_time = (end_time - start_time)*1000 print("time is %d ms" %execution_time ) return wrapper @deco def f(): print("hello") time.sleep(1) print("world") if __name__ == '__main__': f()
這里的deco函數(shù)就是最原始的裝飾器,它的參數(shù)是一個(gè)函數(shù),然后返回值也是一個(gè)函數(shù)。
其中作為參數(shù)的這個(gè)函數(shù)f()就在返回函數(shù)wrapper()的內(nèi)部執(zhí)行。然后在函數(shù)f()前面加上@deco,
f()函數(shù)就相當(dāng)于被注入了計(jì)時(shí)功能,現(xiàn)在只要調(diào)用f(),它就已經(jīng)變身為“新的功能更多”的函數(shù)了,
(不需要重復(fù)執(zhí)行原函數(shù))。
擴(kuò)展1:帶有固定參數(shù)的裝飾器
import time def deco(f): def wrapper(a,b): start_time = time.time() f(a,b) end_time = time.time() execution_time = (end_time - start_time)*1000 print("time is %d ms" % execution_time) return wrapper @deco def f(a,b): print("be on") time.sleep(1) print("result is %d" %(a+b)) if __name__ == '__main__': f(3,4)
擴(kuò)展2:無(wú)固定參數(shù)的裝飾器
import time def deco(f): def wrapper(*args, **kwargs): start_time = time.time() f(*args, **kwargs) end_time = time.time() execution_time_ = (end_time - start_time)*1000 print("time is %d ms" %execution_time) return wrapper @deco def f(a,b): print("be on") time.sleep(1) print("result is %d" %(a+b)) @deco def f2(a,b,c): print("be on") time.sleep(1) print("result is %d" %(a+b+c)) if __name__ == '__main__': f2(3,4,5) f(3,4)
擴(kuò)展3:使用多個(gè)裝飾器,裝飾一個(gè)函數(shù)
import time def deco01(f): def wrapper(*args, **kwargs): print("this is deco01") start_time = time.time() f(*args, **kwargs) end_time = time.time() execution_time = (end_time - start_time)*1000 print("time is %d ms" % execution_time) print("deco01 end here") return wrapper def deco02(f): def wrapper(*args, **kwargs): print("this is deco02") f(*args, **kwargs) print("deco02 end here") return wrapper @deco01 @deco02 def f(a,b): print("be on") time.sleep(1) print("result is %d" %(a+b)) if __name__ == '__main__': f(3,4)
''' this is deco01 this is deco02 hello,here is a func for add : result is 7 deco02 end here time is 1003 ms deco01 end here '''
裝飾器調(diào)用順序
裝飾器是可以疊加使用的,那么使用裝飾器以后代碼是啥順序呢?
對(duì)于Python中的”@”語(yǔ)法糖,裝飾器的調(diào)用順序與使用 @ 語(yǔ)法糖聲明的順序相反。
在這個(gè)例子中,”f(3, 4) = deco01(deco02(f(3, 4)))”。
Python內(nèi)置裝飾器
在Python中有三個(gè)內(nèi)置的裝飾器,都是跟class相關(guān)的:staticmethod、classmethod 和property。
staticmethod 是類靜態(tài)方法,其跟成員方法的區(qū)別是沒(méi)有 self 參數(shù),并且可以在類不進(jìn)行實(shí)例化的情況下調(diào)用
classmethod 與成員方法的區(qū)別在于所接收的第一個(gè)參數(shù)不是 self (類實(shí)例的指針),而是cls(當(dāng)前類的具體類型)
property 是屬性的意思,表示可以通過(guò)通過(guò)類實(shí)例直接訪問(wèn)的信息
對(duì)于staticmethod和classmethod這里就不介紹了,通過(guò)一個(gè)例子看看property。
注意,對(duì)于Python新式類(new-style class),如果將上面的 “@var.setter” 裝飾器所裝飾的成員函數(shù)去掉,則Foo.var 屬性為只讀屬性,使用 “foo.var = ‘var 2′” 進(jìn)行賦值時(shí)會(huì)拋出異常。但是,對(duì)于Python classic class,所聲明的屬性不是 read-only的,所以即使去掉”@var.setter”裝飾器也不會(huì)報(bào)錯(cuò)。
總結(jié)
本文介紹了Python裝飾器的一些使用,裝飾器的代碼還是比較容易理解的。只要通過(guò)一些例子進(jìn)行實(shí)際操作一下,就很容易理解了。
關(guān)于python裝飾器帶參數(shù)的使用方式就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的參考價(jià)值,可以學(xué)以致用。如果喜歡本篇文章,不妨把它分享出去讓更多的人看到。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。