裝飾器:(語法糖)python
1 嵌套函數 在一個函數的函數體內,用def聲明一個新函數 2 def foo(): 3 print('in the foo.') 4 def bar(): 5 print('in the bar.') 6 bar() #要調用bar須要在在函數體內調用,相似局部變量 7 foo()
裝飾器例子:僅針對註釋的幾段,對其進行排序,以下紅字app
1 import time #python的debug都是先讀取最外層框架(最外層沒有縮進),最外層中若是涉及到調用,再接着運行調用內容。 第一步 2 3 def timer(func): #當讀取到 @timer的時候,至關於運行 test1 = timer(test1),因此會返回來讀取 warpper 第三步 4 def warpper(*args,**kwargs): 5 start_time = time.time() 6 func(*args,**kwargs) #此時纔是真正意義上運行 test1函數 第六步
return func(*args,**kwargs) #保證fun()返回值也不變 7 stop_time = time.time() 8 print('in the test1() %s'%(stop_time-start_time)) 9 return warpper #把test1看成實參傳遞給 timer,timer(test1),此時返回的是 函數warpper的內存地址 第四步 10 11 #而後此時運行到 python裏的語法【@timer】 12 @timer #至關於 test1 = timer(test1),返回warpper的內存地址,此時若是運行 test1(),至關於 warpper(),warpper就開始執行其函數體內的語句 第二步 13 def test1(): 14 time.sleep(1) 15 print('in the test1')
return ‘from test1’ 16 test1() #此時運行的 test1()已經不是直接運行 test1函數了,是通過@timer,轉換成運行 warpper()了 第五步
裝飾器進階版,裝飾器自己帶參數框架
1 user = 'gkx' 2 pass_1 = '123' 3 def decorator(auth_type): 4 print("auth type",auth_type) 5 def outer_warpper(func): 6 def warpper(*args,**kwargs): 7 if auth_type == 'local': 8 username = input("id") 9 password = input("password") 10 if username == user and password == pass_1: 11 print('\033[32;1mwelcome\033[0m') 12 res = func(*args,**kwargs) 13 print("after decorator") 14 return res 15 else: 16 print('\033[31;1mwrong info\033[0m') 17 elif auth_type == 'ldap': 18 print('我不會') 19 return warpper 20 return outer_warpper #當訪問到這裏的返回值時候,會繼續執行 warpper,而後執行邏輯就和上面提到的timer同樣了 21 22 23 24 @decorator(auth_type='local') #這裏分紅兩部分看,第一部分是 調用decorator(auth_type = 'local'),此時返回outer_wrapper的內存地址
#在第一部分的基礎上,此時加上@,變成了 @outer_wrapper,至關於 homepage = outer_wrapper(wrapper),再返回了wrapper的內存地址
25 def homepage():
26 print('home page')
27 return 'from home'
29 @decorator(auth_type='ldap') 30 def bbs(): 31 print('in bbs') 32 33 print(homepage()) 34 bbs()
裝飾器三個重要補充:ide
#一共有三個 # 第一個 from functools import wraps def outer(func): @wraps(func) #wraps模塊 def inner(*args,**kwargs): print('裝飾前') ret = func(*args,**kwargs) print('裝飾後') return ret return inner @outer def holiday(day): ''' :param day: days of vacation :return: ''' print("放假%s"%day) return '好開心' print(holiday.__name__) #import wraps後此時打印holiday函數名,不然是 inner函數名 print(holiday.__doc__) ret = holiday(3) print(ret) # 第二個,當裝飾器帶參數 import time FLAG = False def out_timmer(flag): def timmer(func): def inner(*args,**kwargs): if flag: start = time.time() ret = func() end = time.time() print(start-end) return ret else: ret = func() return ret return inner return timmer @out_timmer(FLAG) #能夠當作兩部 1, timmer = out_timmer(FLAG) 2, @timmer def shop1(): time.sleep(0.01) print('buy first thing') @out_timmer(FLAG) def shop2(): time.sleep(0.01) print('buy second thing') shop1() shop2() #第三個 函數被多個裝飾器調用 def wrapper1(func): #func-----> f def inner1(): print('wrapper1,befor func') ret = func() print('wrapper1,after func') #這一句運行完,可是inner2還沒結束,要返回inner2繼續運行【print('wrapper2,after func')】 return ret return inner1 def wrapper2(func): #func-----> inner1 inner1傳給了wrapper2 def inner2(): print('wrapper2,befor func') #運行完這一句,下一句運行inner1,故返回到wrapper1繼續運行 ret = func() #inner1 print('wrapper2,after func') return ret return inner2 @wrapper2 #wrapper1 執行完後,執行wrapper2 可是此時傳入的不是f,是 inner1,至關於 wrapper(inner1) == inner2 而後繼續運行warpper2 @wrapper1 #先執行到這裏,由於語法糖要找離它最近的函數。wrapper2沒找到,故往下運行。此時函數 f傳給wrapper1 至關於 f = wrapper1(f) 即爲 inner1 def f(): print('in the f') f() #--------->>調用inner2