python裝飾器

閱讀本文需要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("{[]}{{}}[]")
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章