国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

Python裝飾器-裝飾流程,執(zhí)行順序

cpupro / 3313人閱讀

摘要:最近看到一個(gè)關(guān)于的題文章其中的一個(gè)是裝飾器的順序問題就想寫篇博客回顧下裝飾器首先強(qiáng)烈推薦很久之前看的一篇博文翻譯理解中的裝飾器關(guān)于什么是裝飾器看這篇文章就好了這里主要想寫關(guān)于多個(gè)裝飾器的執(zhí)行流程裝飾順序示例代碼初始化初始化輸出結(jié)果初始化初始

最近看到一個(gè)關(guān)于Flask的CTF(RealWorld CTF 2018 web題bookhub)文章
其中的一個(gè)trick是裝飾器的順序問題,就想寫篇博客回顧下裝飾器~

首先強(qiáng)烈推薦很久之前看的一篇博文
(翻譯)理解PYTHON中的裝飾器
關(guān)于什么是裝飾器看這篇文章就好了~
這里主要想寫關(guān)于多個(gè)裝飾器的執(zhí)行流程
裝飾順序

示例代碼

# import pdb;pdb.set_trace()

def functionOne(function_to_decorate):
    print("functionOne初始化")
  
    def wrapperOne():
pass
    return wrapperOne

def functionTwo(function_to_decorate):
    print("functionTwo初始化")
  
    def wrapperTwo():
pass
    return wrapperTwo

@functionOne
@functionTwo
def testFunction():
    pass

# 輸出結(jié)果
functionTwo初始化
functionOne初始化
從上面我們能得知:裝飾順序,就近裝飾
然后我們利用下面的代碼進(jìn)行一步探究
如下我們得知:執(zhí)行這段代碼,相當(dāng)于:
首先,將testFunction函數(shù)打包給wrapperTwo,由于沒有調(diào)用,functionTwo整體返回了wrapperTwo,而沒有執(zhí)行
然后,functionOne將wrapperTwo作為參數(shù),打包成wrapperOne
# import pdb;pdb.set_trace()

def functionOne(function_to_decorate):
    print("functionOne初始化")
  
    def wrapperOne():
print("第一處"+function_to_decorate.__name__)
function_to_decorate()
    return wrapperOne

def functionTwo(function_to_decorate):
    print("functionTwo初始化")
  
    def wrapperTwo():
print("第二處"+function_to_decorate.__name__)
function_to_decorate()
    return wrapperTwo

@functionOne
@functionTwo
def testFunction():
    print("index")

testFunction()

#輸出結(jié)果
functionTwo初始化
functionOne初始化
第一處wrapperTwo
第二處testFunction
index
執(zhí)行順序
從上面的第二段代碼我們已經(jīng)能看出部分執(zhí)行順序了
就是它會(huì)優(yōu)先執(zhí)行我們打包好的wrapperOne,因?yàn)閺钠鹗嫉膖estFunction,wrapperTwo都已經(jīng)打包在wrapperOne
可以說成執(zhí)行順序,就遠(yuǎn)執(zhí)行
我們繼續(xù)執(zhí)行下面的代碼:
# import pdb;pdb.set_trace()

def functionOne(function_to_decorate):
    print("functionOne初始化")
  
    def wrapperOne():
print("第一處"+function_to_decorate.__name__)
function_to_decorate()
print("wrapperOne")
    return wrapperOne

def functionTwo(function_to_decorate):
    print("functionTwo初始化")
  
    def wrapperTwo():
print("第二處"+function_to_decorate.__name__)
function_to_decorate()
print("wrapperTwo")
    return wrapperTwo

@functionOne
@functionTwo
def testFunction():
    print("index")

testFunction()

# 輸出結(jié)果
functionTwo初始化
functionOne初始化
第一處wrapperTwo
第二處testFunction
index
wrapperTwo
wrapperOne
這個(gè)執(zhí)行順序可能也困擾了很多人,現(xiàn)在我們從輸出結(jié)果看
對照代碼,就很容易清楚了,執(zhí)行到wrapperOne中的function_to_decorate時(shí)
其實(shí)相當(dāng)于跳轉(zhuǎn)到了函數(shù)wrapperTwo,然后執(zhí)行wrapperTwo
Flask @login_require
從上面的幾個(gè)例子我們應(yīng)該大概了解了,多個(gè)裝飾器進(jìn)行裝飾以及執(zhí)行的順序
我們來看這道CTF題目,我們首先需要知道的是Flask中路由就是一個(gè)裝飾
from flask import Flask

app = Flask(__name__)
app.debug = True

# import pdb;pdb.set_trace()

# 為了更好的控制輸出,自定義了loginRequire裝飾器
def loginRequire(function_to_decorate):
    print("loginRequire初始化")
  
    def wrapperTwo():
print("loginRequire裝飾成功")
print(function_to_decorate.__name__)
return function_to_decorate()
    return wrapperTwo

@loginRequire
@app.route("/up")
def up():
    return "裝飾路由放在上面!"

@app.route("/down")
@loginRequire
def down():
    return "裝飾路由放在下面!"

if __name__ == "__main__":
    app.run()

# 分別訪問兩個(gè)url輸出結(jié)果
loginRequire初始化
loginRequire初始化
 * Debugger is active!
 * Debugger PIN: 244-957-971
 * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
127.0.0.1 - - [24/Aug/2018 19:01:30] "GET /up HTTP/1.1" 200 -
loginRequire裝飾成功
down
127.0.0.1 - - [24/Aug/2018 19:01:35] "GET /down HTTP/1.1" 200 -
從輸出結(jié)果我們能清楚的看到up的裝飾,并沒有執(zhí)行裝飾器
如果按照我們上面的分析,無論在上面還是下面都會(huì)執(zhí)行的啊??只是順序不同罷了~
我們利用pdb來一步步調(diào)試查看哪里的問題,部分log如下:
> c:usersayidesktop	est256.py(17)()
-> @loginRequire
(Pdb) s
> c:usersayidesktop	est256.py(18)()
-> @app.route("/up")
(Pdb) s
> c:usersayi.virtualenvs	est-gq7eoxbqlibsite-packagesflaskapp.py(1252)route()->
-> return decorator
(Pdb) s
--Call--
> c:usersayi.virtualenvs	est-gq7eoxbqlibsite-packagesflaskapp.py(1248)decorator()
-> def decorator(f):
(Pdb) f

(Pdb) s
> c:usersayi.virtualenvs	est-gq7eoxbqlibsite-packagesflaskapp.py(1249)decorator()
-> endpoint = options.pop("endpoint", None)
(Pdb) s
> c:usersayi.virtualenvs	est-gq7eoxbqlibsite-packagesflaskapp.py(1250)decorator()
-> self.add_url_rule(rule, endpoint, f, **options)
(Pdb) f

#===================================================================================#
        上方up 下方down
#===================================================================================#
> c:usersayidesktop	est256.py(22)()
-> @app.route("/down")
(Pdb) s
> c:usersayidesktop	est256.py(23)()
-> @loginRequire
(Pdb) s
--Call--
> c:usersayidesktop	est256.py(6)loginRequire()
-> def loginRequire(function_to_decorate):
(Pdb) s
> c:usersayidesktop	est256.py(7)loginRequire()
-> print("loginRequire初始化")
(Pdb) s
loginRequire初始化
> c:usersayidesktop	est256.py(9)loginRequire()
-> def wrapperTwo():
(Pdb) s
> c:usersayidesktop	est256.py(13)loginRequire()
-> return wrapperTwo
(Pdb) s
--Return--
> c:usersayidesktop	est256.py(13)loginRequire()->
-> return wrapperTwo
(Pdb) s
--Call--
> c:usersayi.virtualenvs	est-gq7eoxbqlibsite-packagesflaskapp.py(1248)decorator()
-> def decorator(f):
(Pdb) f
.wrapperTwo at 0x0071C468>
從上面的執(zhí)行流程,打印出不斷出現(xiàn)的f,我們能看出,兩個(gè)順序的f值不同
在up中,f=up()
在down中,f=wrapperTwo()
這點(diǎn)符合預(yù)期,裝飾位置不同,然而在執(zhí)行Flask源碼 add_url_rule時(shí)
如上面log所示,直接添加了f的值
> c:usersayi.virtualenvs	est-gq7eoxbqlibsite-packagesflaskapp.py(1249)decorator()
-> endpoint = options.pop("endpoint", None)
(Pdb) s
> c:usersayi.virtualenvs	est-gq7eoxbqlibsite-packagesflaskapp.py(1250)decorator()
-> self.add_url_rule(rule, endpoint, f, **options)
(Pdb) f

也就是添加路由的時(shí)候會(huì)選擇丟失外層的路由,只裝飾route下方的函數(shù)
在add_url_rule中,有這段注釋:

Basically this example::

    @app.route("/")
    def index():
        pass

Is equivalent to the following::

    def index():
        pass
    app.add_url_rule("/", "index", index)

博客地址

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/42289.html

相關(guān)文章

  • Python】一文弄懂python裝飾(附源碼例子)

    摘要:裝飾器的使用符合了面向?qū)ο缶幊痰拈_放封閉原則。三簡單的裝飾器基于上面的函數(shù)執(zhí)行時(shí)間的需求,我們就手寫一個(gè)簡單的裝飾器進(jìn)行實(shí)現(xiàn)。函數(shù)體就是要實(shí)現(xiàn)裝飾器的內(nèi)容。類裝飾器的實(shí)現(xiàn)是調(diào)用了類里面的函數(shù)。類裝飾器的寫法比我們裝飾器函數(shù)的寫法更加簡單。 目錄 前言 一、什么是裝飾器 二、為什么要用裝飾器 ...

    liuchengxu 評(píng)論0 收藏0
  • python 多個(gè)裝飾的調(diào)用順序

    摘要:如果不使用裝飾器的話,普通的做法可能是在中寫一堆校驗(yàn)代碼來判斷用戶是否登錄,然后決定后面的執(zhí)行邏輯,這樣比較麻煩。 前言 裝飾器是程序開發(fā)中經(jīng)常會(huì)用到的一個(gè)功能,也是python語言開發(fā)的基礎(chǔ)知識(shí),如果能夠在程序中合理的使用裝飾器,不僅可以提高開發(fā)效率,而且可以讓寫的代碼看上去顯的高大上^_^ 使用場景 可以用到裝飾器的地方有很多,簡單的舉例如以下場景 引入日志 函數(shù)執(zhí)行時(shí)間統(tǒng)計(jì) 執(zhí)...

    wapeyang 評(píng)論0 收藏0
  • Python 裝飾執(zhí)行順序迷思

    摘要:探究多個(gè)裝飾器執(zhí)行順序裝飾器是用于封裝函數(shù)或代碼的工具,網(wǎng)上可以搜到很多文章可以學(xué)習(xí),我在這里要討論的是多個(gè)裝飾器執(zhí)行順序的一個(gè)迷思。這時(shí)候你該知道為什么輸出結(jié)果會(huì)是那樣,以及對裝飾器執(zhí)行順序?qū)嶋H發(fā)生了什么有一定了解了吧。 探究多個(gè)裝飾器執(zhí)行順序 裝飾器是Python用于封裝函數(shù)或代碼的工具,網(wǎng)上可以搜到很多文章可以學(xué)習(xí),我在這里要討論的是多個(gè)裝飾器執(zhí)行順序的一個(gè)迷思。 疑問 大部...

    frolc 評(píng)論0 收藏0
  • Python - 裝飾decorator

    摘要:在這種代碼運(yùn)行期間動(dòng)態(tài)增加功能的方式,稱之為裝飾器。四接收特定類型參數(shù)的裝飾器裝飾器可以接收參數(shù),當(dāng)調(diào)用裝飾器返回的函數(shù)時(shí),也就調(diào)用了包裹函數(shù),把參數(shù)傳入包裹函數(shù),它將參數(shù)傳遞給被裝飾的函數(shù)。執(zhí)行結(jié)果執(zhí)行結(jié)果 【題外話】心塞塞 心情down down down 有段時(shí)間沒用裝飾器了,然后然后問著就跪了~~~回來翻了翻資料和代碼...... 一、什么是裝飾器 裝飾器,decor...

    HackerShell 評(píng)論0 收藏0
  • Python中的上下文管理和else塊

    摘要:上下文管理器協(xié)議包含和兩個(gè)方法。因此必要時(shí)在上下文管理器函數(shù)中使用語句防范錯(cuò)誤。構(gòu)建臨時(shí)忽略指定異常的上下文管理器。這是個(gè)基類,用于定義基于類的上下文管理器。塊結(jié)束時(shí),按照后進(jìn)先出的順序調(diào)用棧中各個(gè)上下文管理器的方法。 導(dǎo)語:本文章記錄了本人在學(xué)習(xí)Python基礎(chǔ)之控制流程篇的重點(diǎn)知識(shí)及個(gè)人心得,打算入門Python的朋友們可以來一起學(xué)習(xí)并交流。 本文重點(diǎn): 1、掌握if語句之外的el...

    Michael_Lin 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<