裝飾器
函數(shù)裝飾器旬迹,將其他函數(shù)功能增強(qiáng)求类,實(shí)現(xiàn)函數(shù)代碼重用,函數(shù)功能重用椿猎。性能測(cè)試,插日志犯眠,抽離出大量和函數(shù)無關(guān)的
裝飾器:
- 裝飾器本身是一個(gè)函數(shù),用于裝飾其他函數(shù)
- 功能:增強(qiáng)被裝飾函數(shù)的功能
裝飾器一般接受一個(gè)函數(shù)對(duì)象作為參數(shù)鸯旁,以對(duì)其進(jìn)行增強(qiáng)
def deco(func):
def wrapper():
print('please say something:')
func()
print('no zuo no die')
return wrapper
@deco
def show():
print('hello')
show()
閉包
函數(shù)對(duì)象(變量名為函數(shù)名)
函數(shù)體
函數(shù)的參數(shù):位置參數(shù)铺罢,關(guān)鍵字參數(shù)残炮,argv位置參數(shù),*kwargv關(guān)鍵字參數(shù)泉瞻,參數(shù)分解賦值
函數(shù)可以嵌套蛋勺,在函數(shù)中定義并調(diào)用鸠删,在函數(shù)中定義函數(shù),并將其返回就叫做閉合函數(shù),也就是閉包
功用:內(nèi)層函數(shù)記憶外刃泡?層函數(shù)調(diào)用的變量
In [12]: def f(x):
....: def f2(y):
....: return x ** y
....: return f2
....:
In [13]: f(3)
Out[13]: <function __main__.f2>
In [14]: type(f(3)) # f(3) 是一個(gè)函數(shù)
Out[14]: function
In [15]: ff = f(3)
In [16]: ff(4)
Out[16]: 81
In [17]: ff(5)
Out[17]: 243
In [18]: type(ff(4)) # ff(4)是一個(gè)整數(shù)
Out[18]: int
一切皆對(duì)象
In [27]: def hi():
....: print('hello')
....:
In [28]: hi()
hello
In [29]: greet = hi # 函數(shù)名不過是函數(shù)體的個(gè)變量名,在不需要調(diào)用時(shí)烘贴,可直接作為變量拿來用
In [30]: greet()
hello
In [31]: del hi
In [32]: hi()
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
<ipython-input-32-9c04baa18e05> in <module>()
----> 1 hi()
NameError: name 'hi' is not defined
In [33]: greet()
hello
在函數(shù)中定義函數(shù)
從函數(shù)中返回函數(shù)
將函數(shù)作為參數(shù)傳遞給函數(shù)
藍(lán)本規(guī)范:
from functools import wraps
def decorator_name(f):
@wraps(f)
def decorated(*args, **kwargs):
if not can_run:
return "Function will not run"
return f(*args, **kwargs)
return decorated
@decorator_name
def func():
return("Function is running")
can_run = True
print(func())
# Output: Function is running
can_run = False
print(func())
# Output: Function will not run
注意:@wraps接受一個(gè)函數(shù)來進(jìn)行裝飾桨踪,并加入了復(fù)制函數(shù)名稱、注釋文檔铺峭、參數(shù)列表等等的功能汽纠。這可以讓我們?cè)谘b飾器里面訪問在裝飾之前的函數(shù)的屬性。
使用場(chǎng)景
授權(quán)
裝飾器能有助于檢查某個(gè)人是否被授權(quán)去使用一個(gè)web應(yīng)用的端點(diǎn)(endpoint)莉炉。它們被大量使用于Flask和Django web框架中。這里是一個(gè)例子來使用基于裝飾器的授權(quán):
from functools import wraps
def requires_auth(f):
@wraps(f)
def decorated(*args, **kwargs):
auth = request.authorization
if not auth or not check_auth(auth.username, auth.password):
authenticate()
return f(*args, **kwargs)
return decorated
日志
日志是裝飾器運(yùn)用的另一個(gè)亮點(diǎn)絮宁。這是個(gè)例子:
from functools import wraps
def logit(func):
@wraps(func)
def with_logging(*args, **kwargs):
print(func.__name__ + " was called")
return func(*args, **kwargs)
return with_logging
@logit
def addition_func(x):
"""Do some math."""
return x + x
result = addition_func(4)
# Output: addition_func was called
帶參數(shù)的裝飾器
在函數(shù)中嵌入裝飾器
裝飾器類