前言python裝飾器本質(zhì)上就是一個(gè)函數(shù),它可以讓其他函數(shù)在不需要做任何代碼變動(dòng)的前提下增加額外的功能,裝飾器的返回值也是一個(gè)函數(shù)對(duì)象。 計(jì)算函數(shù)運(yùn)行時(shí)間假設(shè)你寫(xiě)了幾個(gè)函數(shù),有一天領(lǐng)導(dǎo)心血來(lái)潮說(shuō),你把每個(gè)函數(shù)的運(yùn)行時(shí)長(zhǎng)(結(jié)束時(shí)間-開(kāi)始時(shí)間)統(tǒng)計(jì)下,作為一個(gè)python實(shí)習(xí)生的你可能會(huì)這樣寫(xiě) 原始函數(shù)import time
def func_a():
print("hello")
time.sleep(0.5)
def func_b():
print("world")
time.sleep(0.8)
if __name__ == '__main__':
func_a()
func_b() 添加運(yùn)行時(shí)長(zhǎng)作為一個(gè)實(shí)習(xí)生的你,可能想到的解決辦法如下 import time
def func_a():
start = time.time()
print("hello")
time.sleep(0.5)
end = time.time()
print("運(yùn)行時(shí)長(zhǎng):%.4f 秒" % (end-start))
def func_b():
start = time.time()
print("world")
time.sleep(0.8)
end = time.time()
print("運(yùn)行時(shí)長(zhǎng):%.4f 秒" % (end-start))
if __name__ == '__main__':
func_a()
func_b() 運(yùn)行結(jié)果: hello
運(yùn)行時(shí)長(zhǎng):0.5009 秒
world
運(yùn)行時(shí)長(zhǎng):0.8008 秒 上面的代碼雖然滿足了領(lǐng)導(dǎo)的要求,但是如果你寫(xiě)的函數(shù)很多的話,每個(gè)函數(shù)都這樣去添加,會(huì)顯得代碼很臃腫,有很多重復(fù)代碼。 函數(shù)裝飾器裝飾器可以寫(xiě)成函數(shù)式裝飾器,也可以寫(xiě)成一個(gè)類裝飾器,先從簡(jiǎn)單的函數(shù)裝飾器開(kāi)始學(xué)習(xí)。 runtime函數(shù)就是一個(gè)裝飾器了,它對(duì)原函數(shù)做了包裝并返回了另外一個(gè)函數(shù),額外添加了一些功能。在函數(shù)上方使用@語(yǔ)法糖就可以調(diào)用這個(gè)裝飾器了 import time
def runtime(func):
def wrapper():
start = time.time()
f = func() # 原函數(shù)
end = time.time()
print("運(yùn)行時(shí)長(zhǎng):%.4f 秒" % (end-start))
return f
return wrapper
@runtime
def func_a():
print("hello")
time.sleep(0.5)
@runtime
def func_b():
print("world")
time.sleep(0.8)
if __name__ == '__main__':
func_a()
func_b() 運(yùn)行結(jié)果 hello
運(yùn)行時(shí)長(zhǎng):0.5001 秒
world
運(yùn)行時(shí)長(zhǎng):0.8001 秒 函數(shù)帶參數(shù)裝飾器上面的runtime就是一個(gè)簡(jiǎn)單的裝飾器模型了,但并不強(qiáng)壯,如果函數(shù)里面帶有參數(shù),那就不管用了,并且函數(shù)的參數(shù)是不固定的,這時(shí)候就需要用到 import time
def runtime(func):
def wrapper(*args, **kwargs):
start = time.time()
f = func(*args, **kwargs) # 原函數(shù)
end = time.time()
print("運(yùn)行時(shí)長(zhǎng):%.4f 秒" % (end-start))
return f
return wrapper
@runtime
def func_a(a):
print("hello"+a)
time.sleep(0.5)
@runtime
def func_b(b, c="xx"):
print("world"+b+c)
time.sleep(0.8)
if __name__ == '__main__':
func_a("a")
func_b("b", c="xxx") 類裝飾器關(guān)于 import time
class runtime(object):
def __init__(self, func):
self.func = func
def __call__(self, *args, **kwargs):
start = time.time()
f = self.func(*args, **kwargs) # 原函數(shù)
end = time.time()
print("運(yùn)行時(shí)長(zhǎng):%.4f 秒" % (end-start))
return f
@runtime
def func_a(a):
print("hello"+a)
time.sleep(0.5)
@runtime
def func_b(b, c="xx"):
print("world"+b+c)
time.sleep(0.8)
if __name__ == '__main__':
func_a("a")
func_b("b", c="xxx") 裝飾器帶參數(shù)快到年底了,領(lǐng)導(dǎo)說(shuō)運(yùn)行的速度先不要太快了,讓客戶先加錢,然后再以正常的速度顯示,那么現(xiàn)在的需求是讓每個(gè)函數(shù)的運(yùn)行時(shí)間加50%,該如何實(shí)現(xiàn)呢? 函數(shù)裝飾器import time
def runtime(slowly=1):
def wrapper(func):
def inner_wrapper(*args, **kwargs):
start = time.time()
f = func(*args, **kwargs) # 原函數(shù)
end = time.time()
t = end-start
time.sleep((slowly-1)*t) # 延遲效果
new_end = time.time()
print("運(yùn)行時(shí)長(zhǎng):%.4f 秒" % (new_end-start))
return f
return inner_wrapper
return wrapper
@runtime(1.5)
def func_a(a):
print("hello"+a)
time.sleep(0.5)
@runtime(1.5)
def func_b(b, c="xx"):
print("world"+b+c)
time.sleep(0.8)
if __name__ == '__main__':
func_a("a")
func_b("b", c="xxx") 類裝飾器import time
class runtime(object):
def __init__(self, slowly=1):
self.slowly = slowly
def __call__(self, func):
def wrapper(*args, **kwargs):
start = time.time()
f = func(*args, **kwargs) # 原函數(shù)
end = time.time()
t = end-start
time.sleep((self.slowly-1)*t) # 延遲效果
new_end = time.time()
print("運(yùn)行時(shí)長(zhǎng):%.4f 秒" % (new_end-start))
return f
return wrapper
@runtime(1.5)
def func_a(a):
print("hello"+a)
time.sleep(0.5)
@runtime(1.5)
def func_b(b, c="xx"):
print("world"+b+c)
time.sleep(0.8)
if __name__ == '__main__':
func_a("a")
func_b("b", c="xxx") 使用場(chǎng)景用哪些地方需要使用裝飾器呢?
|
|