Python裝飾器
1、簡介
本質:
Python的裝飾器就是一個閉包。
目的:
簡化代碼操作
2、使用裝飾器的原則:不改變被裝飾函數的屬性等性質
-
使用中間人
g對象
幫助傳遞參數 -
使用內層裝飾器
@functools.wraps(view_func)
回復被裝飾函數的屬性等性質(舉例2)
3、 舉例1 :定義驗證登錄狀態的裝飾器
# 使用中間人g對象作為裝飾器和被裝飾函數中的參數傳遞者
from
flask
import
session
,
jsonify
,
g
from
myihome
.
utils
.
response_code
import
RET
import
functools
# python的內置模塊,存放函數工具
# 閉包:外層函數一般就是定義為被裝飾的函數(view_func(例如這里是:set_user_avatar))"的@外層函數"
def
login_required
(
view_func
)
:
# 內層函數一般定義為wrapper,并且由于傳遞的參數不確定,使用*args, **kwargs待定
# @functools.wraps(view_func)這個函數裝飾器專門是用來裝飾內層函數的,
# 1參數:外層函數接受的參數,直接傳給里面的就可以了,
# 2意義:內層裝飾器加上之后會改變一些特性:functools的wraps會將wrapper相關的屬性和名字恢復為view_func的屬性和名字,參考博客的例子2
@functools
.
wraps
(
view_func
)
# 在寫裝飾器的時候需要習慣將這個內層裝飾器補上,避免改變被裝飾函數的特性
def
wrapper
(
*
args
,
**
kwargs
)
:
# 判斷用戶的登錄狀態
user_id
=
session
.
get
(
"user_id"
)
# 如果用戶是登錄的,執行視圖函數
if
user_id
is
not
None
:
# g對象的應用,保存user_id,讓其作為參數傳遞對象,在視圖函數中可以通過g對象獲取保存數據
g
.
user_id
=
user_id
return
view_func
(
*
args
,
**
kwargs
)
else
:
# 如果未登錄,返回未登錄的信息
return
jsonify
(
errno
=
RET
.
SESSIONERR
,
errmsg
=
"用戶未登錄"
)
return
wrapper
# 使用中間人g對象作為裝飾器和被裝飾函數中的參數傳遞者,g對象就是提供來保存數據的
# 在一次請求之中如果涉及到多個函數請求參數的時候就可以使用g對象來傳參數
@login_required
def
set_user_avatar
(
)
:
# 本來是可以直接操作session獲取user_id的,
# 但是使用的裝飾器里面已經獲取到了user_id,由裝飾器的原則,不可能變成 def set_user_avatar(user_id):的,所以可以使用中間人g對象傳遞過來,不必重復操作一遍
# user_id = session.get("user_id")
user_id
=
g
.
user_id
pass
# set_user_avatar() 的執行就是執行wrapper-> wrapper() 直接傳遞參數到wrapper()里面
4、
舉例2:
內層裝飾器
@functools.wraps(func)
的作用
①首先:未加上裝飾器:
def
login_required
(
func
)
:
def
wrapper
(
*
args
,
**
kwargs
)
:
pass
return
wrapper
def
test
(
)
:
"""test python"""
pass
print
(
test
.
__name__
)
print
(
test
.
__doc__
)
Python中萬物皆對象,直接打印出函數test()的名字和說明文檔:
test
test python
②加上裝飾器:
def
login_required
(
func
)
:
def
wrapper
(
*
args
,
**
kwargs
)
:
pass
return
wrapper
@login_required
def
test
(
)
:
"""test python"""
pass
# test -> wrapper :執行test(), 實質是執行wrapper()
print
(
test
.
__name__
)
# wrapper.__name__
print
(
test
.
__doc__
)
# wrapper.__doc__
打印的結果為:
wrapper
None
可見已經改變test()的屬性了,違反了裝飾器的原則。
③加上內層函數裝飾器:
import
functools
def
login_required
(
func
)
:
@functools
.
wraps
(
func
)
def
wrapper
(
*
args
,
**
kwargs
)
:
pass
return
wrapper
@login_required
def
test
(
)
:
"""test python"""
pass
# test -> wrapper
print
(
test
.
__name__
)
# wrapper.__name__
print
(
test
.
__doc__
)
# wrapper.__doc__
打印結果為:
test
test python
可見被裝飾函數的屬性被恢復了。
參考代碼及項目URL:
https://github.com/too-hoo/myiHome/blob/master/myihome/utils/commons.py
更多文章、技術交流、商務合作、聯系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號聯系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元
