閱讀本文需要15分鐘
前言
裝飾器,故名失憶就是裝飾用的,它可以裝飾函數(其他就不知道了),裝飾器用法就是在函數上一句加上
@裝飾器名稱
裝飾器有按功能可分爲函數裝飾器、類裝飾器,按參數分可分爲帶參數和不帶參數,我主要用帶參數的函數裝飾器
裝飾器的應用有:插入日誌、性能測試、事務處理、緩存、權限校驗。。。(感覺好高大上,我用的只是冰山一角)
栗子
假如我們要測試一個函數xxx的運行時間
def xxx(s):
stack = []
paren_map = {')':'(',']':'[','}':'{'}
for c in s:
if c not in paren_map:
stack.append(c)
elif not stack or paren_map[c] != stack.pop():
return False
return not stack
,我們首先想到在調用函數時⏲一次,調用後再⏲一次,兩個時間相減
import time
if __name__ == "__main__":
time.clock()
xxx("{[]}{{}}[]")
print(time.clock())
"""
這裏有必要說明一下time.time()是取時間戳
而time.clock()第一次是取程序運行時間,第二次是取上次取時間到這次的間隔。(有點繞,就是第二次直接輸出就是程序xxx函數運行時間了)
"""
這樣寫固然可以,但是以後你會厭倦這種寫法,因爲每次都要導入
time、前面加
一個函數
,後面加一個函數,以後刪除
也麻煩,而且當我們需要測試運行100次
xxx的運行時間呢?在加一個for i in range(100)???,這樣做的話又要修改縮進
,實在太煩
但是當你使用了裝飾器之後,一切都變得優雅
了。
測試運行xxx所用時間
@timeit
def xxx(s):
stack = []
paren_map = {')':'(',']':'[','}':'{'}
for c in s:
if c not in paren_map:
stack.append(c)
elif not stack or paren_map[c] != stack.pop():
return False
return not stack
if __name__ == "__main__":
xxx("{[]}{{}}[]")
測試運行100次xxx所用時間
@timeit(count=100)
def xxx(s):
stack = []
paren_map = {')':'(',']':'[','}':'{'}
for c in s:
if c not in paren_map:
stack.append(c)
elif not stack or paren_map[c] != stack.pop():
return False
return not stack
if __name__ == "__main__":
xxx("{[]}{{}}[]")
正文
由於裝飾器又涉及嵌套函數
閉包
概念,爲了簡單起見,這些我們略過,按模板來寫就好
同樣是實現⏲功能
不帶參數的函數裝飾器
模板
def decorator(func):
def inner(*args , **kwargs):
ret = func(*args , **kwargs) ##這裏就是相當於運行了一次下面的some_fun
return ret+1 ##我們將結果+1後返回
return inner
@decorator ##爲函數添加裝飾器,這個裝飾器功能就是給結果+1
def some_fun(arg1 , … ,argn):
return 1
ret = some_fun() ##這裏的ret值就是2了
⏲一次
所用時間
def timeit(func):
def inner(*args , **kwargs):
import time
time.clock()
result = func(*args , **kwargs)
return result
print("函數運行時間:{}".format(time.clock()))
return inner
@timeit
def xxx(s):
stack = []
paren_map = {')':'(',']':'[','}':'{'}
for c in s:
if c not in paren_map:
stack.append(c)
elif not stack or paren_map[c] != stack.pop():
return False
return not stack
if __name__ == "__main__":
xxx("{[]}{{}}[]")
帶參數的函數裝飾器
模板
def decorator(arg = 0):
def outer(func):
def inner(*args , **kwargs):
ret = func(*args , **kwargs)
return ret+1
return inner
return outer
@decorator(arg = 1)
def some_fun(arg1 , … ,argn):
return 1
ret = some_fun()
⏲count次
所用時間
def decorator(count=1):
def outer(func):
def inner(*args , **kwargs):
import time
time.clock()
for i in range(count):
result = func(*args , **kwargs)
print("函數運行{}次時間:{}".format(count, time.clock()))
return result
return inner
return outer
@timeit(count=100)
def xxx(s):
stack = []
paren_map = {')':'(',']':'[','}':'{'}
for c in s:
if c not in paren_map:
stack.append(c)
elif not stack or paren_map[c] != stack.pop():
return False
return not stack
if __name__ == "__main__":
xxx("{[]}{{}}[]")