Python修飾器

前話:

python的修飾器可以說是python語言最有靈性的一個功能了,看到網(wǎng)上有各種亂亂的文章,所以想自己寫得親民一下,如有錯誤請指出。

正文:

@fnc & 被修飾函數(shù)無參數(shù)

首先看一組簡單的代碼:

#修飾器
def dec(fn):
    print("此處fn為函數(shù)",fn)
    return fn

@dec
#被修飾函數(shù)
def my_fn():
    return "函數(shù)返回值"

print(my_fn())
>>> 此處fn為函數(shù) <function my_fn at 0x0000020D87993B70>
>>> 函數(shù)返回值

以上的代碼的修飾過程相當(dāng)于my_fn => dec(my_fn)

@fnc & 被修飾函數(shù)有參數(shù)

接下來為被修飾函數(shù)加參數(shù):

def dec(fn):
    print("此處fn為函數(shù)",fn)
    return fn

@dec
def my_fn(a):
    return "函數(shù)返回值為"+str(a)

print(my_fn('參數(shù)'))
>>> 此處fn為函數(shù) <function my_fn at 0x00000230F14C3B70>
>>> 函數(shù)返回值為參數(shù)

此處依然為my_fn => dec(my_fn)

[小插曲]@fnc() & 被修飾函數(shù)無/有參數(shù)

在修飾器和被修飾函數(shù)都帶參數(shù)前,先準(zhǔn)備一個小插曲:

def dec_out():
    print('運(yùn)行了dec_out')
    def dec_in (b):
        print("運(yùn)行了dec_in")
        return b
    return dec_in

@dec_out()
def my_fn(a):
    return "函數(shù)返回值為"+str(a)

print(my_fn('my_fn參數(shù)'))
>>> 運(yùn)行了dec_out
>>> 運(yùn)行了dec_in
>>> 函數(shù)返回值為my_fn參數(shù)

看到這么多函數(shù)不要暈哦,我來解釋一下:

  1. 首先運(yùn)行my_fn函數(shù)時先進(jìn)入了修飾器
  2. 遇到了dec_out時發(fā)現(xiàn)修飾器位置是一個被執(zhí)行的函數(shù)(帶著括號),于是便執(zhí)行了一下
  3. 修飾器就因?yàn)槔锩娴?code>return dec_in就等效成了@dec_out() => @dec_in
  4. 因此my_fn('my_fn參數(shù)')就等效成了dec_in(my_fn)('my_fn參數(shù)')

在這里休息一下,我來解答一下可能存在的疑惑:

Q:為什么上一個情況my_fn => dec(my_fn),這次是dec_in(my_fn)('my_fn參數(shù)')

A:注意細(xì)節(jié)哦,上一個是my_fn,這次是my_fn('my_fn參數(shù)')

[正餐]@fnc(*arg) & 被修飾函數(shù)無/有參數(shù)

到了正餐了,有了上一個的鋪墊,這次的也可以理解了

def dec_out(a):
    print("dec_out收到了",a)
    def dec_in (b):
        print("dec_in收到了",b)
        return b
    return dec_in

@dec_out("修飾器參數(shù)")
def my_fn(a):
    return "函數(shù)返回值為"+str(a)

print(my_fn('my_fn參數(shù)'))
>>> dec_out收到了 修飾器參數(shù)
>>> dec_in收到了 <function my_fn at 0x0000022432253AE8>
>>> 函數(shù)返回值為my_fn參數(shù)

有沒有預(yù)知到這次的結(jié)局呢?某種意義上很清楚明了了:

  • @dec_out("修飾器參數(shù)")在運(yùn)行的因?yàn)?code>return dec_in等效成了@dec_in,進(jìn)而my_fn('my_fn參數(shù)')等效成了dec_in (my_fn)('my_fn參數(shù)')

這里我就不人肉DEBUG來給各位講解了。

[加餐]多重@fnc(*arg) & 被修飾函數(shù)無/有參數(shù)

一下比較簡單:

def dec_first(fn):
    print("dec_first運(yùn)行了")
    return fn

def dec_second(fn):
    print("dec_second運(yùn)行了")
    return fn

@dec_first
@dec_second
def my_fn():
    return "my_fn運(yùn)行了"

print(my_fn())
>>> dec_second運(yùn)行了
>>> dec_first運(yùn)行了
>>> my_fn運(yùn)行了

從以上可以看出修飾器的運(yùn)行順序是從臨近被修飾函數(shù)開始的。但是不要認(rèn)為解釋器是直接從第二個修飾器開始解釋的。

請看一下代碼:

def dec_first_out(a):
    print("dec_first_out收到了",a)
    def dec_first_in(fn):
        print("dec_first_in運(yùn)行了")
        return fn
    return dec_first_in

def dec_second(fn):
    print("dec_second運(yùn)行了")
    return fn

@dec_first_out('第一個參數(shù)')
@dec_second
def my_fn():
    return "my_fn運(yùn)行了"

print(my_fn())
>>> dec_first_out收到了 第一個參數(shù)
>>> dec_second運(yùn)行了
>>> dec_first_in運(yùn)行了
>>> my_fn運(yùn)行了

由此可以看出,解釋器看到了最上方的修飾器處于運(yùn)行狀態(tài)(有括號)于是運(yùn)行,后再按上面咱們發(fā)現(xiàn)的行為運(yùn)行。

[最后的晚餐]被修飾的修飾器

聽起來復(fù)雜,實(shí)際還是這么回事:

def dec_dec(fn):
    print("dec_dec運(yùn)行了")
    return fn
@dec_dec
def dec(fn):
    print("dec運(yùn)行了")
    return fn

@dec
def my_fn():
    return "my_fn運(yùn)行了"

print(my_fn())
>>> dec_dec運(yùn)行了
>>> dec運(yùn)行了
>>> my_fn運(yùn)行了

看到這里應(yīng)該已經(jīng)清楚了吧,最有靈性的功能也是按部就班的執(zhí)行的。

總結(jié)

總的來看,python的修飾器可以這么理解:

  • 如果@后方不是一個函數(shù)名稱,則運(yùn)行到為一個函數(shù)名稱為止,這種情況才會被解釋成一個 參數(shù)為被修飾函數(shù) 的函數(shù)調(diào)用過程。(這么說是為了通俗明了,實(shí)際這么說欠妥)
  • 多層的(閉包)函數(shù)作為修飾器要注意最終運(yùn)行結(jié)果為一個函數(shù)名
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 前言 Python的修飾器的英文名叫Decorator,當(dāng)你看到這個英文名的時候,你可能會把其跟Design Pa...
    linheimx閱讀 658評論 0 4
  • 前言 對python的修飾器的理解一直停留在"使用修飾器把函數(shù)注冊為事件的處理程序"的層次,也是一知半解;這樣拖著...
    MrYun閱讀 24,695評論 3 35
  • “耐根要結(jié)婚了” “是呀,也不小了,該結(jié)婚了?!?“我怎么聽說是因?yàn)橐o老方?jīng)_喜呀” “老方呀,真是的,應(yīng)該享福的...
    依云70后閱讀 990評論 0 6
  • 文|希昕 參賽編號385 謹(jǐn)以此篇,送給2018年高考考生 如今,四月,春意正濃! 去年,四月,我,在三年五班奮浴...
    錷篐閱讀 400評論 2 25
  • 一、積極主動 生活中是否經(jīng)常聽到,或者我們也有這樣的消極情緒“我根本沒時間做”、“他把我氣瘋了”、“要是某某更耐心...
    一只奮力翱翔的鴿子閱讀 342評論 1 0

友情鏈接更多精彩內(nèi)容