Python多個Decorator裝飾器的使用
阿新 • • 發佈:2019-02-08
在tornado專案中一些RequestHandler中的get(),post()方法需要驗證登陸使用者和使用者許可權,並返回template或者json。
class IndexHandler(RequestHandler):
@render_json
@login_required
@permission_required(10001)
get(self):
pass
對於同一個get()方法使用了多個裝飾器,執行的順序一般是自上而下,但太多個裝飾器個人認為還是比較難以理解。
Demo
def first_decorator (func):
print('--first--')
def first_wrapper(*args, **kwargs):
print('------first---%s---' % func.__name__)
return func(*args, **kwargs)
return first_wrapper
def second_decorator(func):
print('--second--')
def second_wrapper(*args, **kwargs):
print('------second---%s---' % func.__name__)
return func(*args, **kwargs)
return second_wrapper
@first_decorator
@second_decorator
def test_func_1():
print('excute %s' % inspect.stack()[0][3])
定義了兩個裝飾器,並裝飾了函式test_func_1(),此時應該輸出:
--second--
--first--
------first---second_wrapper---
------second---test_func_1 ---
excute test_func_1
拆分裝飾器@語法糖以後,等價於。
def test_func_1():
print('excute %s' % inspect.stack()[0][3])
first_decorator(second_decorator(test_func_1))()
進一步拆分。
second_wrapper = second_decorator(test_func_1) # 返回實際是second_wrapper
# second()
first = first_decorator(second_wrapper) # second_wrapper 傳入first_decorator()
first()
實際上首先執行了second_decorator(test_func_1)
返回second_wrapper
函式,而此時--second--
已經列印了。
然後first_decorator()
接受之前返回的second_wrapper
並返回了first_wrapper
函式,而此時--first--
已經列印了。
最後執行first_wrapper(second_wrapper)()
,先打印出------first---second_wrapper---
了,因為此時first_decorator
中接受的func
是second_wrapper
,然後執行func(*args, **kwargs)
即second_wrapper()
,打印出------second---test_func_1---
,最後執行test_func_1()
,列印excute test_func_1
(感覺仍有問題,需要重新整理一下思路。)
模擬Handler
def login_required(func):
def wrapper(self, *args, **kwargs):
if not self.current_user:
# 未登入情況
raise Exception('please login')
else:
return func(self, *args, **kwargs)
return wrapper
def permission_required(permission_code):
def decorator(func):
def wrapper(self, *args, **kwargs):
if not self.current_user.permission_code == permission_code:
raise Exception('not have permission')
else:
return func(self, *args, **kwargs)
return wrapper
return decorator
class User():
def __init__(self, name, permission_code=0):
self.name = name
self.permission_code = permission_code
class BaseHandler():
def __init__(self, current_user=None):
self.current_user = current_user
@login_required
@permission_required(1)
def get(self):
print('get success')
return 'hello'
@permission_required(1)
@login_required
def post(self):
print('post success')
return 'hello'
是否能簡化成一個裝飾器?
# 簡化成一個裝飾器?
def check_login_permission(permission_code=0):
# 0預設不需要許可權
def decorator(func):
def wrapper(self, *args, **kwargs):
if not self.current_user:
raise Exception('please login')
if permission_code and self.current_user.permission_code != permission_code:
raise Exception('not have permission')
return func(self, *args, **kwargs)
return wrapper
return decorator
class NewBaseHandler():
def __init__(self, current_user=None):
self.current_user = current_user
@check_login_permission(0)
def get(self):
print('get success')
return 'hello'
try:
# user_1 = User('JiangW_1', 1)
# new_base_handler = NewBaseHandler(user_1)
new_base_handler = NewBaseHandler(None)
new_base_handler.get()
except Exception as e:
print(e)