国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > Python > 正文

Python中裝飾器兼容加括號和不加括號的寫法詳解

2020-01-04 16:56:26
字體:
來源:轉載
供稿:網友

使用Django的時候,我發現一個很神奇的裝飾器: @login_required, 這是控制一個view的權限的,比如一個視圖必須登錄才可以訪問,可以這樣用:

@login_requireddef my_view(request): ... return render(...)

同時,如果要達到這樣一種效果:如果用戶沒有登錄,那么就把用戶重定向到登錄界面,可以這樣用:

@login_required(login_url='/accounts/login/')def my_view(request): ... return render(...)

所以這個裝飾器可以帶括號寫,又可以不帶括號寫。很神奇有沒有。正常的接收參數的裝飾器,就算沒參數也應該寫成@login_required的

好奇去查了一下,在stackoverflow找到一種實現,挺有意思的。先曬出答案:

def doublewrap(f): ''' a decorator decorator, allowing the decorator to be used as: @decorator(with, arguments, and=kwargs) or @decorator ''' @wraps(f) def new_dec(*args, **kwargs):  if len(args) == 1 and len(kwargs) == 0 and callable(args[0]):   # actual decorated function   return f(args[0])  else:   # decorator arguments   return lambda realf: f(realf, *args, **kwargs)  return new_dec

使用起來很簡單,只要給裝飾器用@doublewrap裝飾一下,這個裝飾器就支持寫括號和不寫括號兩種寫法了。

def test_doublewrap(): from util import doublewrap from functools import wraps   @doublewrap def mult(f, factor=2):  '''multiply a function's return value'''  @wraps(f)  def wrap(*args, **kwargs):   return factor*f(*args,**kwargs)  return wrap  # try normal @mult def f(x, y):  return x + y  # try args @mult(3) def f2(x, y):  return x*y  # try kwargs @mult(factor=5) def f3(x, y):  return x - y  assert f(2,3) == 10 assert f2(2,5) == 30 assert f3(8,1) == 5*7

原理也不難,只有短短不到10行代碼。

裝飾器我們都知道,是用來處理一個函數,返回一個新的函數的(如果你不理解裝飾器,可以看一下這個經典的解釋)。

new_func = decorator(func)

我們使用的,就是被裝飾器裝飾的新函數了。裝飾器只是一個語法糖,其實它也是一個函數,給它傳入一個函數作為參數,就返回一個新的函數。那么既然裝飾器也是一個函數,我們就可以用裝飾器裝飾這個函數。也就是,“裝飾器的裝飾器”。

裝飾器第一個參數肯定是原函數,如果裝飾器可以接收參數的話,要么第一個參數是原函數,后面跟別的參數;要么就只有原函數一個參數。所以,我們這個“裝飾器的裝飾器”做的事情就是,判斷裝飾器接收的參數,如果只有一個并且第一個參數是可調用的(callable),那么這就是一個無參數的裝飾器(不需要加括號)。如果還有別的參數,就返回一個生成裝飾器的函數(decorator_maker)。

裝飾器是一個函數。裝飾器被裝飾過之后,這個裝飾器運行之前就會先運行裝飾器的裝飾器的代碼,也就是我們的doublewrapp。然后返回值可能是一個裝飾器,也可能是一個裝飾器的maker(有參數的裝飾器),然后裝飾器再執行,裝飾原函數。

這里有點繞,因為本來裝飾器里面一般就會有三四層函數了,(maker, decorator, wrapper, realfunc),再加上一個裝飾器的裝飾器,會有點理解困難。如果理解不了,最好不要對著網上的博文(包括本文)企圖格物致知了,多去看看代碼,多寫一寫。

總結

以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作能帶來一定的幫助,如果有疑問大家可以留言交流,謝謝大家對VEVB武林網的支持。

參考資料

How to create a Python decorator that can be used either with or without parameters?

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 河津市| 广宗县| 吐鲁番市| 林州市| 阿合奇县| 鲜城| 新安县| 深泽县| 弥渡县| 湖州市| 枝江市| 临洮县| 赤水市| 兴义市| 大竹县| 佛冈县| 合水县| 桂林市| 桂平市| 双牌县| 蚌埠市| 霍山县| 汉中市| 太仓市| 泗水县| 尉犁县| 安福县| 汉源县| 凤冈县| 远安县| 浦江县| 万山特区| 锡林浩特市| 泰宁县| 潜江市| 乡宁县| 武威市| 襄城县| 铜梁县| 遵义市| 岳普湖县|