Python 函式裝飾器及用法

2021-10-02 02:58:23 字數 3861 閱讀 9368

函式裝飾器的工作原理是怎樣的呢?假設用 funa() 函式裝飾器去裝飾 funb() 函式,如下所示:

#funa 作為裝飾器函式

deffuna

(fn)

:#...

fn()# 執行傳入的fn引數

#...

return

'...'

@funa

deffunb()

:#...

實際上,上面程式完全等價於下面的程式:

def

funa

(fn)

:#...

fn()# 執行傳入的fn引數

#...

return

'...'

deffunb()

:#...

funb = funa(funb)

將 b 作為引數傳給 a() 函式;

將 a() 函式執行完成的返回值反饋回 b。

舉個例項:

#funa 作為裝飾器函式

deffuna

(fn)

:print

("c語言中文網"

) fn(

)# 執行傳入的fn引數

print

("")return

"裝飾器函式的返回值"

@funa

deffunb()

:print

("學習 python"

)

程式執行流程為:

c語言中文網

學習 python

在此基礎上,如果在程式末尾新增如下語句:

print

(funb)

其輸出結果為:

裝飾器函式的返回值
顯然,被「@函式」修飾的函式不再是原來的函式,而是被替換成乙個新的東西(取決於裝飾器的返回值),即如果裝飾器函式的返回值為普通變數,那麼被修飾的函式名就變成了變數名;同樣,如果裝飾器返回的是乙個函式的名稱,怎麼被修飾的函式名依然表示乙個函式。

實際上,所謂函式裝飾器,就是通過裝飾器函式,在不修改原函式的前提下,來對函式的功能進行合理的擴充。在分析 funa() 函式裝飾器和 funb() 函式的關係時,細心的讀者可能會發現乙個問題,即當 funb() 函式無引數時,可以直接將 funb 作為 funa() 的引數傳入。但是,如果被修飾的函式本身帶有引數,那應該如何傳值呢?

比較簡單的解決方法就是在函式裝飾器中巢狀乙個函式,該函式帶有的引數個數和被裝飾器修飾的函式相同。例如:

def

funa

(fn)

:# 定義乙個巢狀函式

defsay

(arc)

:print

("python教程:"

,arc)

return say

@funa

deffunb

(arc)

:print

("funb():"

, a)

funb(

"/python"

)程式執行結果為:

python教程: http:

/python

這裡有必要給讀者分析一下這個程式,其實,它和如下程式是等價的:

def

funa

(fn)

:# 定義乙個巢狀函式

defsay

(arc)

:print

("python教程:"

,arc)

return say

deffunb

(arc)

:print

("funb():"

, a)

funb = funa(funb)

funb(

"/python"

)

如果執行此程式會發現,它的輸出結果和上面程式相同。

顯然,通過 funb() 函式被裝飾器 funa() 修飾,funb 就被賦值為 say。這意味著,雖然我們在程式顯式呼叫的是 funb() 函式,但其實執行的是裝飾器巢狀的 say() 函式。

但還有乙個問題需要解決,即如果當前程式中,有多個(≥ 2)函式被同乙個裝飾器函式修飾,這些函式帶有的引數個數並不相等,怎麼辦呢?

最簡單的解決方式是用 *args 和 **kwargs 作為裝飾器內部巢狀函式的引數,*args 和 **kwargs 表示接受任意數量和型別的引數。舉個例子:

def

funa

(fn)

:# 定義乙個巢狀函式

defsay

(*args,

**kwargs)

: fn(

*args,

**kwargs)

return say

@funa

deffunb

(arc)

:print

("c語言中文網:"

,arc)

@funa

defother_funb

(name,arc)

:print

(name,arc)

funb(

"")other_funb(

"python教程:"

,"/python"

)執行結果為:

c語言中文網: http:

python教程: http:

/python

上面示例中,都是使用乙個裝飾器的情況,但實際上,python 也支援多個裝飾器,比如:

@funa

@funb

@func

deffun()

:#...

上面程式的執行順序是裡到外,所以它等效於下面這行**:

fun = funa( funb ( func (fun)

))

比如**很多頁面需要登入後才能操作,這裡就可以把這個登入判斷寫成乙個裝飾器函式;

需要登入才能操作的頁面直接呼叫上面寫的函式 @裝飾器函式,把當前頁作為乙個引數傳過去;

裝飾器函式接收到頁面後,判斷當前使用者是否登入,如果登入則返回2步真正的頁面,否則跳轉到登入頁面;

例項參考:《django(十六)基於模板的登入案例》

def

login_required

(view_func)

:'''登入判斷裝飾器'''

def(request,

*view_args,

**view_kwargs)

:# 判斷使用者是否登入

if request.session.has_key(

'islogin'):

# 使用者已登入,呼叫對應的檢視

return view_func(request,

*view_args,

**view_kwargs)

else

:# 使用者未登入,跳轉到登入頁

return redirect(

'/login'

)

呼叫:

# /change_pwd

@login_required #作用:把此頁面作為乙個引數傳到login_required裡

defchange_pwd

(request)

:'''顯示修改密碼頁面'''

return render(request,

'booktest/change_pwd.html'

)

Python學習筆記 函式裝飾器及用法

函式裝飾器 當程式使用 函式 比如函式a 裝飾另乙個函式 比如函式b 時,實際上完成如下兩步 將被修飾的函式 函式b 作為引數傳給 符號引用的函式 函式a 將函式b替換 裝飾 成第1步的返回值 事例def funa fn print a fn 執行傳入的fn引數 return fkit 下面裝飾效果...

python函式裝飾器的用法

一 什麼是裝飾器 用來給其他固定函式增加其他功能的一種函式。裝飾器的實現是函式裡面巢狀函式,讓其他函式在不需要做任何 改動的前提下增加額外功能。裝飾器需要傳遞乙個函式,返回值也是乙個函式物件 二 裝飾器的應用舉例 1.需求 使用者登陸驗證的裝飾器,如果使用者登陸成功,則執行被裝飾的函式,如果登陸失敗...

python函式裝飾器 的用法

是python中的乙個語法糖,decorator表示宣告乙個函式裝飾器,這條宣告語句中,decorator通過 被宣告為了函式裝飾器,其作用是對緊接著定義的函式進行進一步的裝飾,並返回與被裝飾函式同名的函式。decorator用法規則 1 裝飾器函式decorator需要先定義 2 當要裝飾乙個函式...