1.裝飾器定義和原則
定義:裝飾器本質是一個函數,(裝飾其它函數)就是爲其它函數添加附加功能。
原則:不能修改被裝飾函數的源代碼;不能修改被裝飾函數的調用方式。
2.實現裝飾器知識儲備
1.函數即變量
2.高階函數
a.把一個函數名當做實參傳給另一個函數--》可以實現不修改被裝飾函數的源代碼,爲其它函數添加附加功能
import time def test1(): time.sleep(3) print("this is test1") def test2(func): start_time = time.time() func() stop_time = time.time() print("this func run time is %s"%(stop_time-start_time)) test2(test1)
b.返回值中包含函數名-->可以實現不修改被裝飾函數的調用方式
def test3(): print("this is test3") def test4(func): print("附加功能") return func test3 = test4(test3) test3()
注:調用函數的時候不加括號表示調用該函數內存地址如:print(test3)--><function test3 at 0x003E7660>,加括號表示執行該函數
3.嵌套函數 ,在一個函數裏再次聲明一個函數
def test5(): print("this is test5") def test6(): #類似於局部變量,只能在局部調用 print("this is test6") test6() test5()
4.高階函數+嵌套函數--》裝飾器
a.裝飾器舉例1
import time #裝飾器:增加計算函數運行時間的功能 def timer(func): def deco(*args,**kwargs): #在裝飾器中增加*args,**kwargs之後,無論原函數參數的個數是多少,都可以適應 start_time = time.time() res = func(*args,**kwargs) stop_time = time.time() print("this func run time is %s"%(stop_time-start_time)) return res #在裝飾器中增加return res之後,可以返回原函數中的返回值 return deco #下面的1,2也就是裝飾器執行的過程 #原函數 @timer #1、 @timer 實際上是在執行“test1 = timer(test1)”-->將原test1 內存地址傳給func,然後直接將deco的內存地址返回到test1 def test1(): time.sleep(3) print("this is test1") #test1 = timer(test1) test1() #2、這時test1()相當於直接調用deco(*args,**kwargs),而deco裏的func還是指向的原test1的內存地址 @timer def test2(name): time.sleep(1) print("this is %s"%(name)) test2("fengxiaoli") @timer def test3(name): time.sleep(2) print("this is %s"%(name)) return "test3 res" print(test3("cx")) #先執行test3(cx),再打印test3的返回結果
b.裝飾器舉例2
#給網頁增加一個驗證的功能,並且home頁面用本地驗證,bbs頁面用ldap驗證 user = "fengxiaoli" passwd = "123456" def auth(auth_type): def out_wrapper(func): def wrapper(*args,**kwargs): if auth_type == "local": user_name = input("請輸入用戶名:").strip() password = input("請輸入密碼:").strip() if user_name == user and password == passwd: res = func(*args,**kwargs) print("welcome to home!") return res else: print("用戶名或密碼錯誤") else: print("ldap login") return wrapper return out_wrapper #原函數 def index(): print("this is index") @auth(auth_type="local") #相對於裝飾器1中的例子,這裏調用裝飾器的時候使用了參數,在1中裝飾器不變得情況下直接在外在嵌套了一層函數,最外層函數接收的就是裝飾器中的參數 def home(): print("this is home page") home() @auth(auth_type="ldap") def bbs(): print("this is bbs page") bbs()