python 帶參與不帶參裝飾器的使用與流程分析
阿新 • • 發佈:2018-12-09
一.什麼是裝飾器
裝飾器是用來給函式動態的新增功能的一種技術,屬於一種語法糖。通俗一點講就是:在不會影響原有函式的功能基礎上,在原有函式的執行過程中額外的新增上另外一段處理邏輯
二.裝飾器功能實現的技術基礎--閉包
什麼是閉包?閉包就是:一個內部函式被一個外部函式當做返回值進行返回,並且內部函式引用了外部函式提供的變數, 此時將內部函式和引用的外部變數構成的整體稱為閉包
閉包的特徵?閉包有一個明顯的特徵就是:引用了外部變數的閉包能夠讓外部函式不被釋放,如果外部函式被釋放,就會導致內部函式訪問變數時出錯
閉包中內部函式如何修改外部函式提供的變數? python3 如果要在閉包內修改外部函式提供的變數,需要使用(nonlocal 變數名稱) 進行宣告變數不是本地變數,才能進行更改 , python2 中,需要在閉包外先將變數新增到一個列表裡,再在閉包內通過下標取出變數,然後進行更改使用。
三.裝飾器的使用場景
引入日誌
函式執行時間統計
執行函式前預備處理
執行函式後清理功能
許可權校驗等場景
快取
三.不帶參的裝飾器的使用與流程分析
裝飾階段:呼叫外層函式 (在呼叫被裝飾函式前,已經經歷裝飾階段) 執行階段:呼叫內層函式和 內層函式的函式體中的func指向的 裝飾器下的函式 (執行階段就是呼叫被裝飾函式的時候)
#coding=utf-8 from django.shortcuts import redirect from django.http import HttpResponseRedirect from rest_framework.response importResponse def login(func): # 登入驗證裝飾器,如果未登入就轉到登入頁面 def login_func(request, *args, **kwargs) if user_id in request.session return func(request, *args, **kwargs) else: 返回還是一個response物件,可以用來設定cookie,session等 redi = HttpResponseRedirect('./user/login') # 設定cookie,當用戶尚未登入時就進行需要登入後才能進行的操作, # 就先記住使用者的當前所處的頁面,登入時,通過取回cookie則將使用者登入前所處的頁面返回 redi.set_cookies('url', request.get_full_path()) return redi return login_func # 返回時使用了變數名稱 api_list 進行接收 @login def api_list(request): return Response(status=status.HTTP_200_OK)
api_list(request) # 假設存在這麼一個呼叫邏輯。當然了,在實際的介面,並不是我們開發人員手動去呼叫的,有使用者請求了才會觸發。 # request.get_full_path() 獲取帶引數的當前請求所在的頁面的url # request.path 獲取去掉引數的當前請求所在的頁面的url
流程說明:
1.裝飾階段
首先,會存在這麼一個執行流程(這是直譯器去進行的):
api_list = login(api_list),
將被裝飾的函式的引用進行傳參,呼叫裝飾器的外層函式,返回內層函式的引用, 返回值使用了被裝飾函式的函式名稱進行接收,此時的狀態就是:
api_list 指向了 原來 login_func 包含的函式體,func 指向了 原來api_list所指向的函式體,注意是 原來!
2.執行階段
當使用 ret = api_list(request) 進行函式的呼叫時,因為 api_list 已經指向了 原來 login_func 所包含的函式體,也就是裝飾器的內層
函式。所以,裝飾器的內層函式開始執行,func被呼叫,因為此時 func 指向了原來 api_list 所包含的函式體,最後,被裝飾函式得到執行
注意:外層函式和內層函式也同樣要接收 被裝飾函式所接收了的引數
四.帶參的裝飾器的使用與流程分析。。。有空再寫