一、函數(shù)裝飾器
1、函數(shù)裝飾器的定義:
裝飾器的實(shí)現(xiàn)是函數(shù)里面嵌套函數(shù)
在不改變?cè)瘮?shù)的基礎(chǔ)上,給函數(shù)增加功能",把一個(gè)函數(shù)當(dāng)作參數(shù),返回一個(gè)替代版的函數(shù)
本質(zhì)上:返回函數(shù)的函數(shù)
裝飾器需要傳遞一個(gè)函數(shù), 返回值也是一個(gè)函數(shù)對(duì)象.
示例1:調(diào)用新函數(shù)
如下outer函數(shù)就是一個(gè)裝飾器,func是形參接收的一個(gè)函數(shù),inner是返回的函數(shù)
示例2:
2、語(yǔ)法糖:@+裝飾器函數(shù)名(@desc)
使用裝飾器來(lái)裝飾一個(gè)函數(shù),只需要在開(kāi)頭加上@+裝飾器函數(shù)名就可以
運(yùn)行結(jié)果如下:
3、導(dǎo)入string模塊,使得我們可以調(diào)用與字符串操作相關(guān)的函數(shù)
4、裝飾器需求:獲取每個(gè)函數(shù)的執(zhí)行時(shí)間
1.函數(shù)執(zhí)行之前計(jì)算時(shí)間
2.函數(shù)執(zhí)行之后計(jì)算時(shí)間
導(dǎo)入random模塊和string模塊,來(lái)生成100個(gè)大寫(xiě)或小寫(xiě)字母為元素組成的列表
運(yùn)行結(jié)果如下:
問(wèn)題1:被裝飾的函數(shù)有返回值的時(shí)候怎么辦?
python函數(shù)返回值return,函數(shù)中一定要有return才是完整的函數(shù)
#接收被裝飾函數(shù)的返回值
res = fun(*args,**kwargs)
return res
運(yùn)行結(jié)果為:
問(wèn)題2:如何保留被裝飾函數(shù)的函數(shù)名和幫助文檔信息
導(dǎo)入import functools模塊來(lái)保留被裝飾函數(shù)的函數(shù)名和幫助文檔信息
運(yùn)行結(jié)果如下:
.__name__:用來(lái)記錄函數(shù)的名稱(chēng)
.__doc__:用來(lái)記錄函數(shù)的文檔字符串
5、map和匿名函數(shù)
map( )傳入的第一個(gè)參數(shù)是一個(gè)函數(shù),第二個(gè)參數(shù)是一個(gè)序列
5、多個(gè)裝飾器的順序
一個(gè)函數(shù)的裝飾器可以有對(duì)個(gè),如果要使用多個(gè)裝飾器,在函數(shù)的定義之前加上對(duì)應(yīng)裝飾器的語(yǔ)法糖就可以
多個(gè)裝飾器的使用順序:當(dāng)有多個(gè)裝飾器時(shí),從下到上調(diào)用裝飾器
運(yùn)行結(jié)果為:
6、帶有參數(shù)的裝飾器
@log('westos')
log('westos') –> 返回值是add_log
add = add_log(add)
運(yùn)行結(jié)果為:
二、裝飾器練習(xí)
1、 創(chuàng)建裝飾器, 要求如下:
1). 創(chuàng)建add_log裝飾器, 被裝飾的函數(shù)打印日志信息;
2). 日志格式為: [字符串時(shí)間] 函數(shù)名: xxx, 運(yùn)行時(shí)間:xxx, 運(yùn)行返回值結(jié)果:xxx
運(yùn)行結(jié)果為:
2、需求:用戶(hù)登陸驗(yàn)證的裝飾器 is_login
1)如果用戶(hù)登陸成功,則執(zhí)行被裝飾的函數(shù)
2)如果用戶(hù)登陸不成功,則執(zhí)行登陸函數(shù)
運(yùn)行結(jié)果為:
3、編寫(xiě)裝飾器required_ints, 條件如下:
1)確保函數(shù)接收到的每一個(gè)參數(shù)都是整數(shù);
2) 如果參數(shù)不是整形數(shù), 打印 TypeError:參數(shù)必須為整形
運(yùn)行結(jié)果為:
4、多和裝飾器的應(yīng)用
在我們實(shí)際的應(yīng)用場(chǎng)景中,會(huì)采用多個(gè)裝飾器先驗(yàn)證是否登陸成功再驗(yàn)證權(quán)限
需求1:用戶(hù)登陸驗(yàn)證的裝飾器is_login
1)如果用戶(hù)登陸成功,則執(zhí)行被裝飾的函數(shù)
2)如果用戶(hù)登陸不成功,則顯示未登陸信息
需求2:判斷登陸用戶(hù)是否是超級(jí)用戶(hù)is_root
1)若是超級(jí)用戶(hù)root,則執(zhí)行裝飾函數(shù)
2)若不是超級(jí)用戶(hù),則報(bào)錯(cuò)
運(yùn)行結(jié)果為:
5、帶有參數(shù)的裝飾器練習(xí)
編寫(xiě)裝飾器required_types, 條件如下:
1)當(dāng)裝飾器為@required_types(int,float)確保函數(shù)接收到的每一個(gè)參數(shù)都是int或者float類(lèi)型;
2)當(dāng)裝飾器為@required_types(list)確保函數(shù)接收到的每一個(gè)參數(shù)都是list類(lèi)型;
3)當(dāng)裝飾器為@required_types(str,int)確保函數(shù)接收到的每一個(gè)參數(shù)都是str或者int類(lèi)型;
4)如果參數(shù)不滿(mǎn)足條件, 打印 TypeError:參數(shù)必須為xxxx類(lèi)型
運(yùn)行結(jié)果為: