小編給大家分享一下Python中裝飾器的使用方法,相信大部分人都還不怎么了解,因此分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后大有收獲,下面讓我們一起去了解一下吧!
員工經(jīng)過(guò)長(zhǎng)期磨合與沉淀,具備了協(xié)作精神,得以通過(guò)團(tuán)隊(duì)的力量開(kāi)發(fā)出優(yōu)質(zhì)的產(chǎn)品。創(chuàng)新互聯(lián)堅(jiān)持“專注、創(chuàng)新、易用”的產(chǎn)品理念,因?yàn)椤皩W⑺詫I(yè)、創(chuàng)新互聯(lián)網(wǎng)站所以易用所以簡(jiǎn)單”。公司專注于為企業(yè)提供成都網(wǎng)站制作、網(wǎng)站設(shè)計(jì)、外貿(mào)網(wǎng)站建設(shè)、微信公眾號(hào)開(kāi)發(fā)、電商網(wǎng)站開(kāi)發(fā),小程序設(shè)計(jì),軟件按需網(wǎng)站開(kāi)發(fā)等一站式互聯(lián)網(wǎng)企業(yè)服務(wù)。
裝飾器的使用
來(lái)看下面的代碼:
import time import random def index(): time.sleep(random.randrange(1,5)) print("welcome to index page") index()
index函數(shù)的作用是程序在隨機(jī)睡眠1到5秒之后,打印一句話?,F(xiàn)在想為index函數(shù)添加一個(gè)新功能:統(tǒng)計(jì)index函數(shù)的運(yùn)行時(shí)間,該怎么做呢??
修改index函數(shù)如下:
import time import random def index(): start_time=time.time() time.sleep(random.randrange(1,5)) print("welcome to index page") end_time=time.time() print("cost time: %s" %(end_time - start_time)) index()
運(yùn)行程序,執(zhí)行結(jié)果如下:
welcome to index page cost time: 2.000999927520752
可以看到,為index函數(shù)添加新功能確實(shí)實(shí)現(xiàn)了,但是卻違反了開(kāi)放封閉原則。在符合開(kāi)放封閉原則的前提下,如果想為index函數(shù)添加新功能,此時(shí)就要使用裝飾器了。
修改代碼
import time import random def index(): time.sleep(random.randrange(1,5)) print("welcome to index page") def timmer(): def inner(): start_time=time.time() index() end_time=time.time() print("run time: %s " %(end_time-start_time)) return inner f=timmer() f()
運(yùn)行程序,查看執(zhí)行結(jié)果
welcome to index page run time: 1.0
從程序執(zhí)行結(jié)果可以看出,index函數(shù)的運(yùn)行時(shí)間已經(jīng)被統(tǒng)計(jì)出來(lái)了,但是查看源碼可以知道,index函數(shù)的源碼確實(shí)沒(méi)有被修改,但是index的調(diào)用方式被修改了。而且還有一個(gè)問(wèn)題就是,timmer這個(gè)裝飾器只能被用來(lái)裝飾index這個(gè)函數(shù),如果以后想統(tǒng)計(jì)別的函數(shù)的運(yùn)行時(shí)間,又要重新定義別的裝飾器,這樣也太不靈活了。
修改上面的代碼
import time import random def timmer(func): def inner(): start_time=time.time() func() end_time=time.time() print("run time: %s " %(end_time-start_time)) return inner def index(): time.sleep(random.randrange(1,5)) print("welcome to index page") index=timmer(index) index()
運(yùn)行程序,查看程序執(zhí)行結(jié)果
welcome to index page run time: 4.0
可以看到,index函數(shù)的源代碼沒(méi)有被修改,index函數(shù)的調(diào)用方式也沒(méi)有改變,但是依然為index函數(shù)添加了統(tǒng)計(jì)時(shí)間的功能,這里使用的就是裝飾器了。
來(lái)分析下上面代碼的執(zhí)行流程:
1.導(dǎo)入time和random模塊,定義index函數(shù)和timmer函數(shù)。
2.把原始的index函數(shù)的內(nèi)存地址作為參數(shù)傳給timmer函數(shù)。
3.timmer函數(shù)內(nèi)部嵌套定義一個(gè)函數(shù)inner,然后返回inner函數(shù)的內(nèi)存地址。
4.timmer函數(shù)執(zhí)行完成,返回timmer函數(shù)的內(nèi)部函數(shù)inner的內(nèi)存地址,然后把inner的內(nèi)存地址賦值給index變量。
5.index是inner函數(shù)的內(nèi)存地址,index變量加括號(hào)運(yùn)行,實(shí)際上就是在運(yùn)行inner函數(shù)。
6.運(yùn)行inner函數(shù),定義程序開(kāi)始時(shí)間。
7.執(zhí)行timmer函數(shù)的變量func,在第2步知道,func這個(gè)變量就是index的內(nèi)存地址,所以這里實(shí)際上是執(zhí)行被裝飾過(guò)后的index函數(shù)。
8.index函數(shù)執(zhí)行完成,定義程序的終止時(shí)間。
9.統(tǒng)計(jì)并打印整個(gè)程序的執(zhí)行過(guò)程中所花費(fèi)的時(shí)間。
這就是裝飾器裝飾index函數(shù)的執(zhí)行流程。
裝飾器的簡(jiǎn)化使用
現(xiàn)在我又有另外一個(gè)函數(shù)home,現(xiàn)在我也想統(tǒng)計(jì)home函數(shù)的運(yùn)行時(shí)間,可以把代碼修改如下:
import time import random def timmer(func): def inner(): start_time=time.time() func() end_time=time.time() print("run time: %s " %(end_time-start_time)) return inner def index(): time.sleep(random.randrange(1,5)) print("welcome to index page") def home(): time.sleep(random.randrange(1,5)) print("welcome to home page") index=timmer(index) index() home=timmer(home) home()
運(yùn)行程序,執(zhí)行結(jié)果如下:
welcome to index page run time: 3.0 welcome to home page run time: 4.0
可以看到,每次調(diào)用統(tǒng)計(jì)程序運(yùn)行時(shí)間的裝飾器timmer,都要先把被調(diào)用的函數(shù)的函數(shù)名作為參數(shù)傳給timmer裝飾器,然后再把timmer裝飾器的執(zhí)行結(jié)果賦值給被調(diào)用的函數(shù)名本身,最后才能調(diào)用被裝飾的函數(shù),太麻煩了有沒(méi)有??
其實(shí)python中的裝飾器可以簡(jiǎn)化成下面的格式:
import time import random def timmer(func): def inner(): start_time=time.time() func() end_time=time.time() print("run time: %s " %(end_time-start_time)) return inner @timmer def index(): time.sleep(random.randrange(1,5)) print("welcome to index page") @timmer def home(): time.sleep(random.randrange(1,5)) print("welcome to home page") index() home()
程序執(zhí)行結(jié)果:
welcome to index page run time: 2.0 welcome to home page run time: 4.0
可以看出,使用@加裝飾器名添加到被裝飾對(duì)象的上方的方式也可以為一個(gè)函數(shù)添加裝飾器中定義的功能。
多個(gè)裝飾器的定義與調(diào)用
在上面的例子里,定義并調(diào)用了一個(gè)統(tǒng)計(jì)程序運(yùn)行時(shí)間的裝飾器timmer,如果現(xiàn)在想為index函數(shù)添加一個(gè)用戶認(rèn)證的功能,可以定義一個(gè)名為auth的裝飾器。
import time import random def auth(func): def wrapper(): while True: user=input("Input your username>>>:").strip() pwd=input("Input your password>>>:").strip() if user== "abcd" and pwd == "abcd1234": print("login successful") func() break else: print("login error") return wrapper @auth def index(): time.sleep(random.randrange(1,5)) print("welcome to index page") index()
運(yùn)行程序:
Input your username>>>:abcd # 先輸入錯(cuò)誤的用戶名和密碼 Input your password>>>:1234 login error # 提示用戶輸入錯(cuò)誤,登錄失敗 Input your username>>>:abcd # 讓用戶再次輸入用戶名和密碼 Input your password>>>:abcd1234 login successful # 登錄成功 welcome to index page # 執(zhí)行index函數(shù)
從程序執(zhí)行結(jié)果可以看出,用戶登錄密碼驗(yàn)證的裝飾器auth已經(jīng)定義并被成功調(diào)用了。
如果想為index函數(shù)添加用戶認(rèn)證的功能,又想統(tǒng)計(jì)index函數(shù)執(zhí)行時(shí)間的功能,在使用裝飾器的情況下該怎么調(diào)用呢?
import time import random def timmer(func): def inner(): start_time=time.time() func() end_time=time.time() print("run time: %s " %(end_time-start_time)) return inner def auth(func): def wrapper(): while True: user=input("Input your username>>>:").strip() pwd=input("Input your password>>>:").strip() if user== "abcd" and pwd == "abcd1234": print("login successful") func() break else: print("login error") return wrapper @timmer @auth def index(): time.sleep(2) print("welcome to index page") index()
在上面的代碼里,為index函數(shù)添加了兩個(gè)裝飾器,現(xiàn)在有一個(gè)問(wèn)題,就是這兩個(gè)裝飾器究竟哪個(gè)先被調(diào)用,哪個(gè)后被調(diào)用呢??
來(lái)分析一下,如果timmer裝飾器先被調(diào)用,那么程序就會(huì)先執(zhí)行timmer裝飾器,然后再執(zhí)行auth裝飾器,提示輸入用戶名和密碼,這樣一來(lái)timmer裝飾器統(tǒng)計(jì)的時(shí)間就會(huì)包括輸入用戶名和密碼的時(shí)間,這個(gè)時(shí)間會(huì)遠(yuǎn)遠(yuǎn)大于index函數(shù)睡眠的2秒種;如果auth裝飾器先被調(diào)用,timmer裝飾器后被調(diào)用,那么timmer裝飾器統(tǒng)計(jì)的運(yùn)行時(shí)間就應(yīng)該只包括index函數(shù)的執(zhí)行時(shí)間值應(yīng)該在2秒多一點(diǎn)點(diǎn)的時(shí)間范圍內(nèi)。
運(yùn)行程序,先輸入錯(cuò)誤的用戶名和密碼以使用程序的執(zhí)行時(shí)間加長(zhǎng)。
Input your username>>>:abcd Input your password>>>:abcd login error Input your username>>>:abcd Input your password>>>:abcd1234 login successful welcome to index page run time: 12.759000062942505
從程序的執(zhí)行結(jié)果可以知道,程序是先運(yùn)行timmer裝飾器,然后才運(yùn)行auth裝飾器,所以timmer統(tǒng)計(jì)的時(shí)間就包括了用戶認(rèn)證的時(shí)間,所以timmer統(tǒng)計(jì)到的程序運(yùn)行時(shí)間遠(yuǎn)遠(yuǎn)大于index睡眠的2秒鐘。
所以這里得出一個(gè)結(jié)論:
當(dāng)一個(gè)函數(shù)同時(shí)被兩個(gè)裝飾器裝飾時(shí),加上函數(shù)最上面的裝飾器先執(zhí)行,加在下面的裝飾器先裝飾。
把上面例子里的timmer裝飾器和auth裝飾器位置互換一下。
import time import random def timmer(func): def inner(): start_time=time.time() func() end_time=time.time() print("run time: %s " %(end_time-start_time)) return inner def auth(func): def wrapper(): while True: user=input("Input your username>>>:").strip() pwd=input("Input your password>>>:").strip() if user== "abcd" and pwd == "abcd1234": print("login successful") func() break else: print("login error") return wrapper @auth @timmer def index(): time.sleep(2) print("welcome to index page") index()
運(yùn)行index函數(shù),依然先輸入錯(cuò)誤的用戶名和密碼,增加用戶認(rèn)證的時(shí)間。
Input your username>>>:abcd Input your password>>>:abcd login error Input your username>>>:abcd Input your password>>>:abcd1234 login successful welcome to index page run time: 2.0
可以看到,這次timmer統(tǒng)計(jì)到的時(shí)間只包含index函數(shù)的運(yùn)行時(shí)間,不包含用戶進(jìn)行認(rèn)證的時(shí)間。
來(lái)分析一下上面例子中,index函數(shù)被timmer裝飾器和auth裝飾器裝飾的代碼裝飾流程。
@auth # index=auth(timmer(index)) @timmer # index=timmer(index) def index(): time.sleep(2) print("welcome to index page")
在上面得出結(jié)論,一個(gè)函數(shù)同時(shí)被兩個(gè)裝飾器時(shí),加在下面的裝飾器先裝飾:
1.timmer裝飾器裝飾原始的index,可以寫成:index=timmer(index)。
2.在timmer裝飾器中,timmer裝飾器實(shí)際上是返回inner的內(nèi)存地址,所以在這里,index=inner。
3.timmer裝飾器裝飾完成后,由auth裝飾器來(lái)裝飾,此時(shí)可以寫成index=auth(index)。
4.這里auth括號(hào)里的index已經(jīng)不再是原始index函數(shù),而是已經(jīng)被timmer裝飾過(guò)后的index了,所以index=auth(timmer(index))。
5.又因?yàn)閠immer裝飾的結(jié)果等于inner函數(shù)的內(nèi)存地址,所以:index=auth(inner)。
至此,兩個(gè)裝飾器的裝飾過(guò)程已經(jīng)知道了,來(lái)看程序的執(zhí)行過(guò)程:
6.程序先執(zhí)行auth裝飾器,進(jìn)入用戶認(rèn)證,請(qǐng)用戶輸入用戶名和密碼。
7.用戶輸入正確的用戶名和密碼后,開(kāi)始執(zhí)行func函數(shù),也已經(jīng)上面分析的inner函數(shù)。
8.timmer裝飾器先定義程序的開(kāi)始運(yùn)行時(shí)間,然后運(yùn)行func函數(shù),也就是原生的index函數(shù)。
9.index函數(shù)先睡眠2秒,然后執(zhí)行print語(yǔ)句,再定義程序的結(jié)束時(shí)間。
10.最后統(tǒng)計(jì)并打印程序的運(yùn)行時(shí)間,至此程序運(yùn)行完畢。
所以這里用戶輸入用戶名和密碼的時(shí)間不會(huì)被timmer裝飾器統(tǒng)計(jì)在內(nèi)。
以上是Python中裝飾器的使用方法的所有內(nèi)容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內(nèi)容對(duì)大家有所幫助,如果還想學(xué)習(xí)更多知識(shí),歡迎關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道!
新聞名稱:Python中裝飾器的使用方法
網(wǎng)頁(yè)路徑:http://muchs.cn/article18/ihjgdp.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站建設(shè)、全網(wǎng)營(yíng)銷推廣、靜態(tài)網(wǎng)站、企業(yè)建站、網(wǎng)站改版、網(wǎng)站導(dǎo)航
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)