1. 程式人生 > >python中的無參裝飾器和有參裝飾器

python中的無參裝飾器和有參裝飾器

tools mysql認證 ati 轉載 lan 單獨 get 原則 url

                  python中的無參裝飾器和有參裝飾器

                                       作者:尹正傑

版權聲明:原創作品,謝絕轉載!否則將追究法律責任。





裝飾器特點:

1>.開放封閉原則,即對擴展是開放的,對修改時封閉的;
2>.裝飾器本質可以是任意可調用的對象,被裝飾的對象也可以是任意可調用對象;
3>.裝飾器的功能是在不修改被裝飾器對象源代碼以及被裝飾器對象的調用方式的前提下為其擴展新功能;
4>.裝飾器本質是函數,(即裝飾其他函數)就是為其他函數添加附加功能。


一.典型裝飾器案例

 1 #!/usr/bin/env python
 2 #_*_coding:utf-8_*_
 3 #@author :yinzhengjie
 4 #blog:http://www.cnblogs.com/yinzhengjie/tag/python%E8%87%AA%E5%8A%A8%E5%8C%96%E8%BF%90%E7%BB%B4%E4%B9%8B%E8%B7%AF/
 5 #EMAIL:[email protected]
 6 
 7 #裝飾器的語法:在被裝飾對象的正上方的單獨一行,@裝飾器名字
 8 import time
 9 import random
10 
11 def RunTime(TheCaller):  #
定義裝飾器 12 def MyCaller(): 13 start_time = time.time() 14 TheCaller() 15 stop_time=time.time() 16 print(run time is %s %(stop_time-start_time)) 17 return MyCaller 18 19 #被裝飾函數 20 @RunTime #等效於index=RunTime(index) 21 def index(): 22 time.sleep(random.randrange(2,4)) #
可以在1-3秒鐘(不包括4秒喲)隨機睡眠指定範圍的時長。 23 print(welecome to INDEX page) 24 25 @RunTime #home=RunTime(home) 26 def home(): 27 time.sleep(random.randrange(1,2)) 28 print(welecome to HOME page) 29 30 index() #MyCaller() 31 home() 32 33 34 35 36 #以上代碼執行結果如下: 37 welecome to INDEX page 38 run time is 2.0000088214874268 39 welecome to HOME page 40 run time is 1.0006351470947266


二.多個裝飾器案例展示
 1 #!/usr/bin/env python
 2 #_*_coding:utf-8_*_
 3 #@author :yinzhengjie
 4 #blog:http://www.cnblogs.com/yinzhengjie/tag/python%E8%87%AA%E5%8A%A8%E5%8C%96%E8%BF%90%E7%BB%B4%E4%B9%8B%E8%B7%AF/
 5 #EMAIL:[email protected]
 6 
 7 #裝飾器的語法:在被裝飾對象的正上方的單獨一行,@裝飾器名字
 8 import time
 9 import random
10 from functools import wraps
11 
12 def RunTime(TheCaller):  #定義裝飾器+
13     @wraps(TheCaller)       #可以讓用戶查看幫助信息的時候查看其自己的源代碼定義的幫助信息。
14     def MyCaller(*args,**kwargs):
15         ‘‘‘
16         Runtime‘s help information
17         ‘‘‘
18         start_time = time.time()
19         res = TheCaller(*args,**kwargs)
20         stop_time=time.time()
21         print(run time is %s %(stop_time-start_time))
22         return res
23 
24     return MyCaller
25 
26 def NewAddAuth(TheCaller):
27     def Auth(*args,**kwargs):
28         name=input(username: )
29         password=input(password: )
30         if name == yinzhengjie and password == 123:
31             print(login successful)
32             res = TheCaller(*args,**kwargs)
33             return res
34         else:
35             print(login error)
36     return Auth
37 
38 #被裝飾函數
39 # @NewAddAuth
40 @RunTime #等效於index=RunTime(index),裝飾器的執行順序是自下而上。
41 def Index():
42     ‘‘‘
43     Index‘s help information
44     ‘‘‘
45     time.sleep(random.randrange(2,4))   #可以在1-3秒鐘(不包括4秒喲)隨機睡眠指定範圍的時長。
46     print(welecome to INDEX page)
47     return "yinzhengjie"
48 
49 @RunTime #home=RunTime(home)
50 def Home(name):
51     ‘‘‘
52       Home‘s help information
53       ‘‘‘
54     time.sleep(random.randrange(1,2))
55     print(welecome to %s HOME page%(name))
56     return 666
57 
58 res1 = Index() #MyCaller()
59 res2 = Home("尹正傑")
60 print("Index return :%s"%(res1))
61 print("Home return :%s"%(res2))
62 # print(help(Index))
63 # print(Index().__doc__)
64 
65 
66 
67 
68 #以上代碼執行結果如下:
69 welecome to INDEX page
70 run time is 3.000018835067749
71 welecome to 尹正傑 HOME page
72 run time is 1.0001890659332275
73 Index return :yinzhengjie
74 Home return :666

三.有參裝飾器

 1 #!/usr/bin/env python
 2 #_*_coding:utf-8_*_
 3 #@author :yinzhengjie
 4 #blog:http://www.cnblogs.com/yinzhengjie/tag/python%E8%87%AA%E5%8A%A8%E5%8C%96%E8%BF%90%E7%BB%B4%E4%B9%8B%E8%B7%AF/
 5 #EMAIL:[email protected]
 6 
 7 ‘‘‘
 8 編寫裝飾器,為多個函數加上認證的功能(用戶的賬號密碼來源於文件),要求登陸成功一次,後續的函數都無需再驗證。
 9 ‘‘‘
10 
11 
12 # user_dic = {
13 #     ‘yinzhengjie‘:‘123‘,
14 #     ‘Golang‘:"666",
15 #     ‘Python‘:"888",
16 # }
17 #
18 # with open("user.db","w",encoding="utf-8")as f:
19 #     f.write(str(user_dic))
20 
21 
22 
23 
24 db_path = "user.db"
25 
26 login_dic ={
27     user:None,
28     "status":False,
29 }
30 
31 def Decorator(AuthType="file"):
32     def auth(func):
33         def wrapper(*args, **kwargs):
34             if AuthType == "file":
35                 if login_dic[user] and login_dic[status]:
36                     res = func(*args, **kwargs)
37                     return res
38                 username = input("username:")
39                 password = input("password:")
40                 with open(db_path, "r", encoding="utf-8")as f:
41                     user_dic = eval(f.read())
42                 if username in user_dic and password == user_dic[username]:
43                     print(login successful)
44                     login_dic[user] = username
45                     login_dic[status] = True
46                     res = func(*args, **kwargs)
47                     return res
48                 else:
49                     print(login error)
50             elif AuthType == "ldap":
51                 print("LDAP認證方式")
52             elif AuthType == "MySQL":
53                 print("MySQL認證方式")
54             else:
55                 print("其他認證方式")
56         return wrapper
57     return auth
58 
59 @Decorator()
60 def Index():
61     print("Welcome to Index!")
62 
63 @Decorator(AuthType="MySQL")
64 def home(name):
65     print("Welecome %s to home page!"%name)
66 
67 Index()
68 home("尹正傑")
69 
70 
71 
72 
73 #以上代碼執行結果如下:
74 username:yinzhengjie
75 password:123
76 login successful
77 Welcome to Index!
78 MySQL認證方式


四.小試牛刀
1.
編寫裝飾器,為多個函數加上認證的功能(用戶的賬號密碼來源於文件),要求登陸成功一次,後續的函數都無需再驗證。
 1 #!/usr/bin/env python
 2 #_*_coding:utf-8_*_
 3 #@author :yinzhengjie
 4 #blog:http://www.cnblogs.com/yinzhengjie/tag/python%E8%87%AA%E5%8A%A8%E5%8C%96%E8%BF%90%E7%BB%B4%E4%B9%8B%E8%B7%AF/
 5 #EMAIL:[email protected]
 6 
 7 
 8 # user_dic = {
 9 #     ‘yinzhengjie‘:‘123‘,
10 #     ‘Golang‘:"666",
11 #     ‘Python‘:"888",
12 # }
13 #
14 # with open("user.db","w",encoding="utf-8")as f:
15 #     f.write(str(user_dic))
16 
17 
18 
19 
20 db_path = "user.db"
21 
22 login_dic ={
23     user:None,
24     "status":False,
25 }
26 
27 def auth(func):
28     def wrapper(*args,**kwargs):
29         if login_dic[user] and login_dic[status]:
30             res = func(*args, **kwargs)
31             return res
32         username = input("username:")
33         password = input("password:")
34         with open(db_path, "r", encoding="utf-8")as f:
35             user_dic = eval(f.read())
36         if username in user_dic and password == user_dic[username]:
37             print(login successful)
38             login_dic[user] = username
39             login_dic[status] = True
40             res = func(*args,**kwargs)
41             return res
42         else:
43             print(login error)
44     return wrapper
45 
46 @auth
47 def Index():
48     print("Welcome to Index!")
49 
50 @auth
51 def home(name):
52     print("Welecome %s to home page!"%name)
53 
54 Index()
55 home("尹正傑")
56 
57 
58 
59 
60 以上代碼執行結果如下:
61 username:yinzhengjie
62 password:123
63 login successful
64 Welcome to Index!
65 Welecome 尹正傑 to home page!

2.編寫下載網頁內容的函數,要求功能是:用戶傳入一個URL,函數返回下載頁面的內容。

 1 #!/usr/bin/env python
 2 #_*_coding:utf-8_*_
 3 #@author :yinzhengjie
 4 #blog:http://www.cnblogs.com/yinzhengjie/tag/python%E8%87%AA%E5%8A%A8%E5%8C%96%E8%BF%90%E7%BB%B4%E4%B9%8B%E8%B7%AF/
 5 #EMAIL:[email protected]
 6 
 7 
 8 from urllib.request import urlopen
 9 import os
10 
11 cache_path=rcache.txt
12 def make_cache(func):
13     def wrapper(*args,**kwargs):
14         if os.path.getsize(cache_path):#說明有緩存
15             print(\033[45m=========有緩存=========\033[0m)
16             with open(cache_path,rb) as f:
17                 res=f.read()
18 
19         else:
20             res=func(*args,**kwargs) #下載
21             with open(cache_path,wb) as f: #制作緩存
22                 f.write(res)
23 
24         return res
25 
26     return wrapper
27 
28 @make_cache
29 def get(url):
30     return urlopen(url).read()
31 
32 
33 print(============first============)
34 print(get(http://www.cnblogs.com/yinzhengjie))
35 print(============second===========)
36 print(get(http://www.cnblogs.com/yinzhengjie))
37 print(============third============)
38 print(get(http://www.cnblogs.com/yinzhengjie))





python中的無參裝飾器和有參裝飾器