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