- 什么時候用裝飾器
想要給函數(shù)動態(tài)的增加一些額外的功能。
Python裝飾器(decorator)在實現(xiàn)的時候,被裝飾后的函數(shù)其實已經(jīng)是另外一個函數(shù)了(函數(shù)名等函數(shù)屬性會發(fā)生改變),為了不影響,Python的functools包中提供了一個叫wraps的decorator來消除這樣的副作用。 - 不加@wraps(func),函數(shù)的名字就是wrapper
- 加@wraps(func),可以保留被裝飾前的函數(shù)名
- 外層函數(shù)嵌套內(nèi)層函數(shù)
- 外層函數(shù)返回內(nèi)層函數(shù)
- 內(nèi)層函數(shù)要使用外層函數(shù)傳遞的參數(shù)
調(diào)用函數(shù),如果帶括號,那么是調(diào)用函數(shù)運行后的結(jié)果,
調(diào)用函數(shù)不帶括號,調(diào)用的是函數(shù)本身
"""__author__= 雍新有"""
import random
import time
from functools import wraps
def record_time(func):
@wraps(func)
def wrapper(*args, **kwargs):
start = time.time()
result = func(*args, **kwargs)
end = time.time()
print(f'{func.__name__}執(zhí)行時間: {end - start}秒')
return result
return wrapper
@record_time
def download(filename):
print(f'開始下載{filename}')
time.sleep(random.randint(5, 15))
print(f'{filename}下載完成')
@record_time
def upload(filename):
print(f'開始上傳{filename}')
time.sleep(random.randint(5, 15))
print(f'{filename}上傳完成')
def main():
print(download.__name__)
print(upload.__name__)
download('Python從入門到住院.pdf')
upload('蒼老師.avi')
download.__wrapped__('Python從入門到住院.pdf')
upload.__wrapped__('蒼老師.avi')
if __name__ == '__main__':
main()
"""
download
upload
開始下載Python從入門到住院.pdf
Python從入門到住院.pdf下載完成
download執(zhí)行時間: 8.000381231307983秒
開始上傳蒼老師.avi
蒼老師.avi上傳完成
upload執(zhí)行時間: 13.00049352645874秒
開始下載Python從入門到住院.pdf
Python從入門到住院.pdf下載完成
開始上傳蒼老師.avi
蒼老師.avi上傳完成
"""
+ 裝飾器在Django中就是中間件middleware
# record_time是一個裝飾器函數(shù)(裝飾別的函數(shù)或者類的函數(shù))
# 裝飾器函數(shù)可以用來裝飾一個類或函數(shù)
# 如果裝飾器用來裝飾函數(shù)那么他的參數(shù)就是被裝飾的函數(shù)(func)
def record_time(func):
# 裝飾器中內(nèi)嵌的wrapper函數(shù)是帶裝飾功能的函數(shù)
# 它除了要執(zhí)行被裝飾的函數(shù)之外要執(zhí)行額外的代碼
def wrapper(*args, **kwargs):
# 在執(zhí)行被裝飾的函數(shù)之前要做什么
result = func(*args, **kwargs)
# 在執(zhí)行被裝飾的函數(shù)之后要做什么
return result
return wrapper()