python基础(第11天)

装饰器的进阶:

1、带参数的装饰器:

可以解决装饰器有时用有时不用的情形。

 1 # 带参数的装饰器主要解决的问题:
 2 # 如果有几百个函数,有的时候需要都加装饰器,有的时候又需要都去掉装饰器,不可能一个一个去添加和去除,带参数的装饰器就应运而生了。
 3 flag = False  # 只需要更改这里,就可以控制被装饰的函数是否执行额外功能
 4 
 5 
 6 def wrapper_outer(flag):
 7     def wrapper(func):
 8         def inner(*args, **kwargs):
 9             if flag:
10                 print("额外的功能")
11                 ret = func(*args, **kwargs)
12                 return ret
13             else:
14                 ret = func(*args, **kwargs)
15                 return ret
16         return inner
17     return wrapper
18 
19 
20 # @wrapper
21 @wrapper_outer(flag)  # 其实这句话相当于执行了:wrapper = wrapper_outer(flag)和@wrapper,装饰器里面并没有变化
22 def shoplist_add():
23     print("添加一件商品")
24 
25 
26 # @wrapper
27 @wrapper_outer(flag)
28 def shoplist_del():
29     print("删除一件商品")
30 
31 
32 # @wrapper
33 @wrapper_outer(flag)
34 def shoplist_update():
35     print("更新一件商品")
36 
37 
38 shoplist_add()
39 shoplist_del()
40 shoplist_update()

2、多个装饰器装饰一个函数:

执行结果类似于套娃,执行过程需要理解。

 1 def wrapper1(func):
 2     def inner1(*args, **kwargs):
 3         print("wrapper1", "before wrap")
 4         ret = func(*args, **kwargs)
 5         print("wrapper1", "after wrap")
 6         return ret
 7     return inner1
 8 
 9 
10 def wrapper2(func):
11     def inner2(*args, **kwargs):
12         print("wrapper2", "before wrap")
13         ret = func(*args, **kwargs)
14         print("wrapper2", "after wrap")
15         return ret
16     return inner2
17 
18 
19 @wrapper2
20 @wrapper1
21 def f():  # 执行结果有点像套娃,具体执行过程需要理解
22     print("in f")
23 
24 
25 """
26 wrapper2 before wrap
27 wrapper1 before wrap
28 in f
29 wrapper1 after wrap
30 wrapper2 after wrap
31 """
32 
33 
34 f()

3、作业:

几个新知识点:

1>os模块中,判断文件大小,可用os.path.getsize(文件名); 

2>urllib模块中,可用urllib.request.urlopen().read()下载源码;

 1 # 1.编写装饰器,为多个函数加上认证的功能(用户的账号密码来源于文件),
 2 # 要求登录成功一次,后续的函数都无需再输入用户名和密码
 3 # flag = False
 4 #
 5 #
 6 # def login(func):
 7 #     def inner(*args, **kwargs):
 8 #         global flag
 9 #         if flag:
10 #             ret = func(*args, **kwargs)
11 #             return ret
12 #         else:
13 #             username = input("username: ")
14 #             password = input("password: ")
15 #             if username == "eric" and password == "123":
16 #                 flag = True
17 #                 ret = func(*args, **kwargs)
18 #                 return ret
19 #             else:
20 #                 print("登陆失败")
21 #     return inner
22 #
23 #
24 # @login
25 # def shoplist_add():
26 #     print("添加一件商品")
27 #
28 #
29 # @login
30 # def shoplist_del():
31 #     print("删除一件商品")
32 #
33 #
34 # shoplist_add()
35 # shoplist_del()
36 
37 #  2.编写装饰器,为多个函数加上记录调用功能,要求每次调用函数都将被调用的函数名称写入文件
38 # def log(func):
39 #     def inner(*args, **kwargs):
40 #         ret = func(*args, **kwargs)
41 #         with open("log.txt","a", encoding="utf-8") as f:
42 #             f.write(func.__name__ + "\n")
43 #         return ret
44 #     return inner
45 #
46 #
47 # @log
48 # def shoplist_add():
49 #     print("添加一件商品")
50 #
51 #
52 # @log
53 # def shoplist_del():
54 #     print("删除一件商品")
55 
56 # shoplist_add()
57 # shoplist_del()
58 
59 # 进阶作业(选做):
60 # 1.编写下载网页内容的函数,要求功能是:用户传入一个url,函数返回下载页面的结果
61 # 2.为题目1编写装饰器,实现缓存网页内容的功能:
62 # 具体:实现下载的页面存放于文件中,如果文件内有值(文件大小不为0),就优先从文件中读取网页内容,否则,就去下载,然后存到文件中
63 from urllib.request import urlopen
64 import os
65 
66 
67 def cache(func):
68     def inner(*args, **kwargs):
69         if os.path.getsize("web_html"):  # 判断文件大小调用OS模块
70             with open("web_html", "rb") as f:
71                 return f.read()  # 如果文件不为空,则直接返回
72         ret = func(*args, **kwargs)
73         with open("web_html", "wb") as f:
74             f.write(b"***" + ret)
75         return ret
76     return inner
77 
78 
79 @cache
80 def get_url(url):
81     code = urlopen(url).read()
82     return code
83 
84 
85 res = get_url("http://baidu.com")
86 print(res)
87 res = get_url("http://baidu.com")
88 print(res)
89 res = get_url("http://baidu.com")
90 print(res)

猜你喜欢

转载自www.cnblogs.com/eric818/p/10351950.html