裝飾器是通過裝飾器函數(shù)修改原函數(shù)的一些功能而不需要修改原函數(shù),在很多場景可以用到它,比如① 執(zhí)行某個測試用例之前,判斷是否需要登錄或者執(zhí)行某些特定操作;② 統(tǒng)計某個函數(shù)的執(zhí)行時間;③ 判斷輸入合法性等。合理使用裝飾器可以極大地提高程序的可讀性以及運行效率。本文將介紹Python裝飾器的使用方法。
創(chuàng)新互聯(lián)建站是一家專業(yè)提供遂昌企業(yè)網(wǎng)站建設(shè),專注與成都網(wǎng)站建設(shè)、成都網(wǎng)站設(shè)計、成都h5網(wǎng)站建設(shè)、小程序制作等業(yè)務(wù)。10年已為遂昌眾多企業(yè)、政府機構(gòu)等服務(wù)。創(chuàng)新互聯(lián)專業(yè)網(wǎng)站制作公司優(yōu)惠進行中。
python裝飾器可以定義如下:
輸出:
python解釋器將test_decorator函數(shù)作為參數(shù)傳遞給my_decorator函數(shù),并指向了內(nèi)部函數(shù) wrapper(),內(nèi)部函數(shù) wrapper() 又會調(diào)用原函數(shù) test_decorator(),所以decorator()的執(zhí)行會先打印'this is wrapper',然后打印'hello world', test_decorator()執(zhí)行完成后,打印 'bye' ,*args和**kwargs,表示接受任意數(shù)量和類型的參數(shù)。
裝飾器 my_decorator() 把真正需要執(zhí)行的函數(shù) test_decorator() 包裹在其中,并且改變了它的行為,但是原函數(shù) test_decorator() 不變。
一般使用如下形式使用裝飾器:
@my_decorator就相當于 decorator = my_decorator(test_decorator) 語句。
內(nèi)置裝飾器@functools.wrap可用于保留原函數(shù)的元信息(將原函數(shù)的元信息,拷貝到對應(yīng)的裝飾器函數(shù)里)。先來看看沒有使用functools的情況:
輸出:
從上面的輸出可以看出test_decorator() 函數(shù)被裝飾以后元信息被wrapper() 函數(shù)取代了,可以使用@functools.wrap裝飾器保留原函數(shù)的元信息:
輸出:
裝飾器可以接受自定義參數(shù)。比如定義一個參數(shù)來設(shè)置裝飾器內(nèi)部函數(shù)的執(zhí)行次數(shù):
輸出:
Python 支持多個裝飾器嵌套:
裝飾的過程:
順序從里到外:
test_decorator('hello world') 執(zhí)行順序和裝飾的過程相反。
輸出:
類也可以作為裝飾器,類裝飾器主要依賴__call__()方法,是python中所有能被調(diào)用的對象具有的內(nèi)置方法(python魔術(shù)方法),每當調(diào)用一個類的實例時,__call__()就會被執(zhí)行一次。
下面的類裝飾器實現(xiàn)統(tǒng)計函數(shù)執(zhí)行次數(shù):
輸出:
下面介紹兩種裝飾器使用場景
統(tǒng)計函數(shù)執(zhí)行所花費的時間
輸出:
在使用某些web服務(wù)時,需要先判斷用戶是否登錄,如果沒有登錄就跳轉(zhuǎn)到登錄頁面或者提示用戶登錄:
--THE END--
裝飾器函數(shù)參數(shù)要傳函數(shù),而不是字符串。
裝飾器函數(shù)特點:
1,參數(shù)為函數(shù)對象
2,使用內(nèi)部函數(shù)
3,返回函數(shù)對象
在你的代碼中:
裝飾器函數(shù)是arg_func(sex)
內(nèi)部函數(shù)是func1()
被裝飾函數(shù)是man()和woman()
所以代碼要改成:
def?arg_func(sex):
def?func1():
sex()
if(sex.__name__=='man'):
print("you?can?'t")
if(sex.__name__=='woman'):
print("you?can")
return?func1
@arg_func
def?man():
print('good?good?study')
@arg_func
def?woman():
print('good?good?study')
man()
woman()
PS:裝飾器就是為了簡化代碼,增加可讀性,方便團隊開發(fā),在不修改原函數(shù)代碼的前提下,通過封裝修改功能,而@修飾就是為了通過原函數(shù)名調(diào)用時,不直接執(zhí)行原函數(shù),而是把原函數(shù)傳遞到裝飾器函數(shù),通過內(nèi)部函數(shù)(閉包)來調(diào)用原函數(shù)。這樣好處,就是統(tǒng)一調(diào)用方式。
裝飾器(decorator)是Python中的高級語法。裝飾的意思就是動態(tài)擴展被裝飾對象的功能。裝飾器可以用于裝飾函數(shù)、方法和類。
一 嵌套函數(shù)
# 定義一個外層函數(shù)def foo(): # 定義了一個內(nèi)部函數(shù) def bar(): print("hello world")
函數(shù)bar是一個定義在foo函數(shù)內(nèi)部的函數(shù)。
Python中的函數(shù)是支持嵌套的,也就是可以在一個函數(shù)內(nèi)部再定義一個函數(shù)。
然后,我們還知道函數(shù)是可以當作變量的,于是我們就可以在foo函數(shù)中把定義的這個bar函數(shù)返回。就像下面這樣:
# 定義一個外層函數(shù)def foo(): # 定義了一個內(nèi)層函數(shù) def bar(): print("hello world") return
barfunc = foo()func() # func -- bar,這里執(zhí)行func其實就相當于執(zhí)行了在foo函數(shù)內(nèi)部定義的bar函數(shù)
二 閉包形態(tài)1
# 閉包形態(tài)1def foo(): name = "Andy" # 外部函數(shù)的局部變量 # 定義了一個內(nèi)部函數(shù) def bar():
print(name) # 雖然bar函數(shù)中沒有定義name變量,但是它可以訪問外部函數(shù)的局部變量name return barfunc =
foo()func() # func -- bar -- 除了是一個函數(shù),還包含一個值(它外層函數(shù)的局部變量)的引用
三 閉包形態(tài)2
# 閉包形態(tài)2def foo(name): # 給一個函數(shù)傳參也相當于給函數(shù)定義了一個局部變量 # 定義了一個內(nèi)部函數(shù) def bar():
print(name) # 內(nèi)部函數(shù)同樣可以獲取到傳到外部函數(shù)的變量(參數(shù)) return barfunc = foo("Andy") #
把“Andy”當成參數(shù)傳入foo函數(shù) -- 其內(nèi)部定義的bar函數(shù)也能拿到這個“Andy”func() # func -- bar --
除了是一個函數(shù),還包含一個值(它外層函數(shù)的參數(shù))的引用
四 裝飾器形態(tài)1
# 還是定義一個外層函數(shù)def foo(name): # 我接收的參數(shù)是一個函數(shù)名 # 定義了一個內(nèi)部函數(shù) def bar():
print("這是新功能。。。") # 新功能 name() # 函數(shù)名加()就相當于執(zhí)行-- 我傳進來原函數(shù)的函數(shù)名,這里就相當于執(zhí)行了原函數(shù)
return bar# 定義一個被裝飾的函數(shù)def f1(): print("hello world.") # 用foo函數(shù)裝飾f1函數(shù)f1 =
foo(f1)# 不改變f1的調(diào)用方式f1() # -- 此時函數(shù)已經(jīng)擴展了新功能
五 裝飾器形態(tài)2
# 還是定義一個外層函數(shù)def foo(name): # 接收的參數(shù)是一個函數(shù)名 # 定義了一個內(nèi)部函數(shù) def bar():
print("這是新功能。。。") # 新功能 name() # 函數(shù)名加()就相當于執(zhí)行-- 傳進來原函數(shù)的函數(shù)名,這里就相當于執(zhí)行了原函數(shù)
return bar# 定義一個被裝飾的函數(shù)# 用foo函數(shù)裝飾f1函數(shù)@foo # 使用f1 =
foo(f1)語法裝飾的話稍顯啰嗦,Python就提供了@語法,讓裝飾過程更簡便def f1(): print("hello world.") #
不改變f1的調(diào)用方式f1() # -- 此時函數(shù)已經(jīng)擴展了新功能。
裝飾器是從英文decorator翻譯過來的,從字面上來看就是對某個東西進行修飾,增強被修飾物的功能,下面我們對裝飾器做下簡單介紹。
一、怎么編寫裝飾器
裝飾器的實現(xiàn)很簡單,本質(zhì)是一個可調(diào)用對象,可以是函數(shù)、方法、對象等,它既可以裝飾函數(shù)也可以裝飾類和方法,為了簡單說明問題,我們實現(xiàn)一個函數(shù)裝飾器,如下代碼:
有了這個裝飾器,我們就可以打印出什么時候開始和結(jié)束調(diào)用函數(shù),對于排查函數(shù)的調(diào)用鏈非常方便。
二、帶參數(shù)的裝飾器
上面的例子無論什么時候調(diào)用sum都會輸出信息,如果我們需要按需輸出信息怎么實現(xiàn)呢,這時就要用到帶參數(shù)的裝飾器了,如下代碼:
對sum使用裝飾器時沒有參數(shù),這時debug為0,所以調(diào)用sum時不會輸出函數(shù)調(diào)用相關(guān)信息。
對multi使用裝飾器時有參數(shù),這時debug為1,所以調(diào)用multi時會輸出函數(shù)調(diào)用相關(guān)信息。
三、函數(shù)名字問題
當我們打印被裝飾后的函數(shù)名字時,不知道大家有沒發(fā)現(xiàn)輸出的不是函數(shù)本身的名字,如下代碼會輸出‘wrap’而不是‘sum’:
有時這種表現(xiàn)并不是我們想要的,我們希望被裝飾后的函數(shù)名字還是函數(shù)本身,那要怎么實現(xiàn)呢?很簡單,只需要引入functools.wraps即可,如下代碼就會輸出‘sum’了:
看完后是不是覺得python裝飾器很簡單,只要了解它的本質(zhì),怎么寫都行,有好多種玩法呢。
簡言之,打個比方,我寫了一個python的插件,提供給用戶使用,但是在使用的過程中我添加了一些功能,可是又不希望用戶改變調(diào)用的方式,那么該怎么辦呢?這個時候就用到了裝飾器。
python裝飾器就是用于拓展原來函數(shù)功能的一種函數(shù),這個函數(shù)的特殊之處在于它的返回值也是一個函數(shù),使用python裝飾器的好處就是在不用更改原函數(shù)的代碼前提下給函數(shù)增加新的功能。一般而言,我們要想拓展原來函數(shù)代碼,比較直接的辦法就是侵入代碼里面修改。
而且裝飾器是程序開發(fā)中經(jīng)常會用到的一個功能,用好了裝飾器,開發(fā)效率如虎添翼,所以這也是Python面試中必問的問題,但對于好多小白來講,這個功能有點繞,自學(xué)時直接繞過去了,然后面試問到了就掛了,因為裝飾器是程序開發(fā)的基礎(chǔ)知識,不懂就太說不過去啦。
講完裝飾器,相信大家對于Python的發(fā)展前景也比較感興趣,隨著人工智能的發(fā)展,Python作為人工智能的首選語言,自然也是發(fā)展得如火如荼?,F(xiàn)在入行,肯定是一個好時機!
分享題目:包含python類裝飾函數(shù)的詞條
轉(zhuǎn)載來于:http://www.rwnh.cn/article22/doohscc.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供做網(wǎng)站、外貿(mào)網(wǎng)站建設(shè)、建站公司、App設(shè)計、網(wǎng)站設(shè)計公司、靜態(tài)網(wǎng)站
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)