python装饰器参数讲解_python装饰器的详细解析
寫在前面:
python裝飾器(fuctional decorators)就是用于拓展原來函數(shù)功能的一種函數(shù),目的是在不改變原函數(shù)名(或類名)的情況下,給函數(shù)增加新的功能。?這個函數(shù)的特殊之處在于它的返回值也是一個函數(shù),這個函數(shù)是內(nèi)嵌“原“”函數(shù)的函數(shù)。
一般而言,我們要想拓展原來函數(shù)代碼,最直接的辦法就是侵入代碼里面修改,例如:
importtimedeff():print("hello")
time.sleep(1)print("world")
這是我們最原始的的一個函數(shù),然后我們試圖記錄下這個函數(shù)執(zhí)行的總時間,那最簡單的做法就是改動原來的代碼:
importtimedeff():
start_time=time.time()print("hello")
time.sleep(1)print("world")
end_time=time.time()
execution_time= (end_time - start_time)*1000
print("time is %d ms" %execution_time)
但是實際工作中,有些時候核心代碼并不可以直接去改,所以在不改動原代碼的情況下,我們可以再定義一個函數(shù)。(但是生效需要再次執(zhí)行函數(shù))
importtimedefdeco(func):
start_time=time.time()
func()
end_time=time.time()
execution_time= (end_time - start_time)*1000
print("time is %d ms" %execution_time)deff():print("hello")
time.sleep(1)print("world")if __name__ == '__main__':
deco(f)print("f.__name__ is",f.__name__)print()
這里我們定義了一個函數(shù)deco,它的參數(shù)是一個函數(shù),然后給這個函數(shù)嵌入了計時功能。但是想要拓展這一千萬個函數(shù)功能,就是要執(zhí)行一千萬次deco()函數(shù),所以這樣并不理想!
接下來,我們可以試著用裝飾器來實現(xiàn),先看看裝飾器最原始的面貌。
importtimedefdeco(f):defwrapper():
start_time=time.time()
f()
end_time=time.time()
execution_time= (end_time - start_time)*1000
print("time is %d ms" %execution_time )returnwrapper
@decodeff():print("hello")
time.sleep(1)print("world")if __name__ == '__main__':
f()
這里的deco函數(shù)就是最原始的裝飾器,它的參數(shù)是一個函數(shù),然后返回值也是一個函數(shù)。
其中作為參數(shù)的這個函數(shù)f()就在返回函數(shù)wrapper()的內(nèi)部執(zhí)行。然后在函數(shù)f()前面加上@deco,
f()函數(shù)就相當(dāng)于被注入了計時功能,現(xiàn)在只要調(diào)用f(),它就已經(jīng)變身為“新的功能更多”的函數(shù)了(不需要重復(fù)執(zhí)行原函數(shù))。
擴展1:帶有固定參數(shù)的裝飾器
importtimedefdeco(f):defwrapper(a,b):
start_time=time.time()
f(a,b)
end_time=time.time()
execution_time= (end_time - start_time)*1000
print("time is %d ms" %execution_time)returnwrapper
@decodeff(a,b):print("be on")
time.sleep(1)print("result is %d" %(a+b))if __name__ == '__main__':
f(3,4)
擴展2:無固定參數(shù)的裝飾器
importtimedefdeco(f):def wrapper(*args, **kwargs):
start_time=time.time()
f(*args, **kwargs)
end_time=time.time()
execution_time_= (end_time - start_time)*1000
print("time is %d ms" %execution_time)returnwrapper
@decodeff(a,b):print("be on")
time.sleep(1)print("result is %d" %(a+b))
@decodeff2(a,b,c):print("be on")
time.sleep(1)print("result is %d" %(a+b+c))if __name__ == '__main__':
f2(3,4,5)
f(3,4)
擴展3:使用多個裝飾器,裝飾一個函數(shù)
importtimedefdeco01(f):def wrapper(*args, **kwargs):print("this is deco01")
start_time=time.time()
f(*args, **kwargs)
end_time=time.time()
execution_time= (end_time - start_time)*1000
print("time is %d ms" %execution_time)print("deco01 end here")returnwrapperdefdeco02(f):def wrapper(*args, **kwargs):print("this is deco02")
f(*args, **kwargs)print("deco02 end here")returnwrapper
@deco01
@deco02deff(a,b):print("hello,here is a func for add :")
time.sleep(1)print("result is %d" %(a+b))if __name__ == '__main__':
f(3,4)
'''this is deco01
this is deco02
hello,here is a func for add :
result is 7
deco02 end here
time is 1003 ms
deco01 end here'''
裝飾器調(diào)用順序
裝飾器是可以疊加使用的,那么使用裝飾器以后代碼是啥順序呢?
對于Python中的”@”語法糖,裝飾器的調(diào)用順序與使用 @ 語法糖聲明的順序相反。在這個例子中,”f(3, 4) = deco01(deco02(f(3, 4)))”。
總結(jié)
以上是生活随笔為你收集整理的python装饰器参数讲解_python装饰器的详细解析的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 整理99种好用的电脑软件
- 下一篇: java初学者笔记总结day6