1、裝飾器的定義
裝飾器本質(zhì)上就是一個(gè)函數(shù)苍在,功能是為其他函數(shù)添加功能
裝飾器的原則:
- 不修改被裝飾函數(shù)的源代碼
- 不修改被裝飾函數(shù)的調(diào)用方式
2绝页、裝飾器的知識(shí)儲(chǔ)備
先聲明一點(diǎn):裝飾器=高階函數(shù)+函數(shù)嵌套+閉包
2.1荠商、高階函數(shù)
定義:
- 函數(shù)的參數(shù)是一個(gè)函數(shù)
- 函數(shù)的返回值是一個(gè)函數(shù)
2.2、嵌套函數(shù)
定義:
- 在一個(gè)函數(shù)的內(nèi)部又定義一個(gè)函數(shù)
注:在嵌套函數(shù)中外部的函數(shù)稱為外函數(shù)续誉,在函數(shù)內(nèi)部定義的函數(shù)稱為內(nèi)函數(shù)
2.3莱没、閉包
定義:
- 內(nèi)函數(shù)調(diào)用外函數(shù)的臨時(shí)變量
- 外函數(shù)的返回值是內(nèi)函數(shù)的引用
代碼示例:
def test(a, b):
def test2():
print(a + b)
return test2
res = test(1, 2)
res() # 相當(dāng)于調(diào)用test2()
3、裝飾器
3.1酷鸦、裝飾器的基本語(yǔ)法格式
通過(guò)上面已經(jīng)知道了 裝飾器=高階函數(shù)+函數(shù)嵌套+閉包郊愧,下面來(lái)實(shí)現(xiàn)一下裝飾器
使用裝飾器統(tǒng)計(jì)函數(shù)test運(yùn)行的時(shí)間
import time
def timer(func):
'計(jì)算程序運(yùn)行時(shí)間的函數(shù)'
def count():
start_time = time.time()
func()
end_time = time.time()
print("運(yùn)行的時(shí)間是%s" % (end_time - start_time))
return count
@timer # @timer就是相當(dāng)與執(zhí)行了timer(test)()
def test():
time.sleep(3)
print("函數(shù)test運(yùn)行結(jié)束")
運(yùn)行時(shí)間:
函數(shù)test運(yùn)行結(jié)束
運(yùn)行的時(shí)間是3.0005695819854736
3.2、函數(shù)加上返回值
當(dāng)我們?cè)趖est函數(shù)中加上一個(gè)return返回值的時(shí)候會(huì)發(fā)現(xiàn)在調(diào)用test函數(shù)的時(shí)候并沒(méi)有返回值井佑,原因是函數(shù)test是在裝飾器函數(shù)的內(nèi)函數(shù)中運(yùn)行的,在內(nèi)函數(shù)中并沒(méi)有return值眠寿,修改如下:
import time
def timer(func):
def count():
start_time = time.time()
res = func()
print(res)
end_time = time.time()
print("運(yùn)行的時(shí)間是%s" %(end_time - start_time))
return count
@timer
def test():
time.sleep(3)
print("函數(shù)test運(yùn)行結(jié)束")
return "這是test的返回值"
test()
3.3躬翁、函數(shù)加上參數(shù)
當(dāng)對(duì)test函數(shù)加上參數(shù)的時(shí)候會(huì)發(fā)現(xiàn)代碼報(bào)錯(cuò),原因是在裝飾器的內(nèi)函數(shù)中我們并沒(méi)有給定形參盯拱,導(dǎo)致test在內(nèi)函數(shù)中運(yùn)行時(shí)無(wú)法接收相應(yīng)的實(shí)參盒发;修改如下:
import time
def timer(func):
def count(*args, **kwargs):
start_time = time.time()
res = func(*args, **kwargs)
print(res)
end_time = time.time()
print("運(yùn)行的時(shí)間是%s" %(end_time - start_time))
return count
@timer
def test(name, age):
time.sleep(3)
print("函數(shù)test運(yùn)行結(jié)束")
print("名字 【%s】,年齡【%s】" %(name, age))
return "這是test的返回值"
test("xiaoming", 20)
運(yùn)行結(jié)果:
函數(shù)test運(yùn)行結(jié)束
名字 【xiaoming】狡逢,年齡【20】
這是test的返回值
運(yùn)行的時(shí)間是3.0006966590881348
3.4宁舰、給裝飾器函數(shù)加上參數(shù)
如果需要給用戶選擇test函數(shù)是否要統(tǒng)計(jì)運(yùn)行時(shí)間的話就要給裝飾器添加一個(gè)參數(shù),判斷是否要統(tǒng)計(jì)test運(yùn)行的時(shí)間奢浑;可使用閉包
情況1:需要進(jìn)行運(yùn)算時(shí)間的統(tǒng)計(jì)
import time
def auth(para = True):
def timer(func):
def count(*args, **kwargs):
if para == True:
start_time = time.time()
res = func(*args, **kwargs)
print(res)
end_time = time.time()
print("運(yùn)行的時(shí)間是%s" %(end_time - start_time))
else:
func(*args, **kwargs)
return count
return timer
@auth(para=True)
def test(name, age):
time.sleep(3)
print("函數(shù)test運(yùn)行結(jié)束")
print("名字 【%s】蛮艰,年齡【%s】" %(name, age))
return "這是test的返回值"
test("xiaoming", 20)
運(yùn)行結(jié)果:
函數(shù)test運(yùn)行結(jié)束
名字 【xiaoming】,年齡【20】
這是test的返回值
運(yùn)行的時(shí)間是3.0004258155822754
情況2:不需要進(jìn)行運(yùn)算時(shí)間的統(tǒng)計(jì)
import time
def auth(para = True):
def timer(func):
def count(*args, **kwargs):
if para == True:
start_time = time.time()
res = func(*args, **kwargs)
print(res)
end_time = time.time()
print("運(yùn)行的時(shí)間是%s" %(end_time - start_time))
else:
func(*args, **kwargs)
return count
return timer
@auth(para=False)
def test(name, age):
time.sleep(3)
print("函數(shù)test運(yùn)行結(jié)束")
print("名字 【%s】雀彼,年齡【%s】" %(name, age))
return "這是test的返回值"
test("xiaoming", 20)
運(yùn)行結(jié)果:
函數(shù)test運(yùn)行結(jié)束
名字 【xiaoming】壤蚜,年齡【20】