天天看點

Day 11:函數裝飾器

在說裝飾器前,先說一個東西,再Python裡,有一個 一切皆對象,一切皆變量。

例:

1 def hello(name="sunjinyao"):
 2     return "hi " + name
 3 print(hello())
 4 # 輸出: 'hi sunjinyao'
 5 # 我們可以将一個函數指派給一個變量,比如
 6 hi = hello
 7 # 我們這裡沒有在使用小括号,因為我們并不是在調用hello函數
 8 # 而是在将它放在greet變量裡頭。我們嘗試運作下這個
 9 print(hi())
10 # 輸出: 'hi sunjinyao'      

裝飾器:就是給其他函數添加新功能。本質也是個函數。

原則:1.不修改被裝飾器函數的源代碼2.不修改被裝飾函數的調用方式

裝飾器 = 高階函數 + 函數嵌套 + 閉包 

高階函數:函數接收的參數是個函數名或者函數的傳回是一個函數名

函數嵌套:定義的函數内還有函數,一層套一層

閉包:在一個外函數中定義了一個内函數,内函數裡運用了外函數的臨時變量,并且外函數的傳回值是内函數的引用。這樣就構成了一個閉包。

裝飾器架構:

1 #例,變量名随需求更改,這裡隻是例子
2 def login(func):#參數func代表要裝飾的函數
3     def inner(*args,**kwargs):#裝飾器的參數不固定
4         #在這裡添加需要的功能
5         ret = func(*args,**kwargs)
6         #再這裡添加需要的功能
7         return ret
8     return inner #沒有()沒有執行      

 例:為TEST函數寫一個裝飾器,統計TEST函數的運作時間

1 #為TEST函數寫一個裝飾器,統計TEST函數的運作時間
 2 import time #導入時間子產品
 3 def time_1(func):#func = my_test
 4     def inner():
 5         start_time = time.time()
 6         ret = func()
 7         stop_time = time.time()
 8         print('函數的運作時間為%s'%(stop_time-start_time))
 9         return ret
10     return  inner
11 @time_1 #必須在所裝飾的函數前使用。
12 #@time_1 == my_test = time_1(my_test)
13 def my_test():
14     time.sleep(3)
15     print('test函數運作完畢')
16   return '這個是my_test的執行結果'
17 #my_test = time_1(my_test)
18 #time_1(my_test) 相當inner函數記憶體位址 因為time1的reture結果是inner
19 print(my_test())#執行了inner函數      

練一練:#編寫裝飾器,為多個函數加上認證功能(使用者密碼來源于檔案),要求登入一次,後續函數無需再輸入密碼。輸入的密碼為3次。

例:檔案内容

abc,123
def,456      
1 login_status = False
 2 def login(func):
 3     def inner(*args,**kwargs):
 4         global login_status
 5         if not login_status:
 6             count = 0
 7             while count < 3:
 8                 user_name =input('請輸入使用者名:')
 9                 pass_word =input('請輸入密碼:')
10                 with open('my_file',encoding='utf8') as passwd_file:
11                     for line in passwd_file:
12                         login_name,login_pwd = line.strip().split(',')
13                         #用,号分割賬号密碼并指派,檔案末尾都是有換行的,去掉空格(strip在前)
14                         if user_name == login_name and pass_word == login_pwd:
15                             login_status = True
16                             print('登入成功')
17                             count += 3 #為了跳出while循環
18                             ret = func(*args, **kwargs)
19                             return ret#跳出了for循環
20                         else:
21                             print('登入失敗,請重新登入')
22                             count += 1
23                             break
24         elif login_status:#在上面循環中,把Login_status狀态改成 True之後,就不需要再次輸入密碼
25             ret = func(*args, **kwargs)
26             return ret
27     return  inner
28 @login
29 def shopping_web():
30     return '購物界面'
31 @login
32 def home_web():
33     return '個人中心'
34 shopping_web()
35 home_web()
36 print(home_web())
37 print(shopping_web())
38 print(home_web())      

轉載于:https://www.cnblogs.com/sunjinchao/p/10896893.html