day 011 装饰器
一、三元运算
(一)三元运算符
a if a>b else b
(二)结果
接收结果的变量 = 条件为真的结果 if 条件 else 条件为假的结果
接收结果的变量 = “真结果” if 条件 else “假结果”
二、装饰器
用到的知识:函数的嵌套、闭包、函数名的本质。
装饰器的本质:在不影响原有函数功能的基础上,增加新功能。
(一)装饰器的原则:
开放封闭原则。
1.对扩展是开放的
为什么要对扩展开放呢?
我们说,任何一个程序,不可能在设计之初就已经想好了所有的功能并且未来不做任何更新和修改。所以我们必须允许代码扩展、添加新功能。
2.对修改是封闭的
为什么要对修改封闭呢?
就像我们刚刚提到的,因为我们写的一个函数,很有可能已经交付给其他人使用了,如果这个时候我们对其进行了修改,很有可能影响其他已经在使用该函数的用户。

1 import time 2 print(time.time()) # 获取当前时间 3 time.sleep(10) #让程序在执行到这个位置的时候停一会儿 4 5 6 def timmer(f): #装饰器函数 7 def inner(): 8 start = time.time() 9 ret = f() #被装饰的函数 10 end = time.time() 11 print(end - start) 12 return ret 13 return inner 14 15 @timmer #语法糖 @装饰器函数名 16 def func(): #被装饰的函数 17 time.sleep(0.01) 18 print('老板好同事好大家好') 19 return '新年好' 20 # func = timmer(func) 21 ret = func() #inner() 22 print(ret)
PS:在pycharm中,使用断点功能 一步一步的走,有助于理解。
(二)装饰器参数
1 def wrapper(param01): # param01 = 装饰器本身的 2 3 def outer(param02): # param02 = 被装饰的函数的函数名称 4 5 def inner(param03): # param03 = 被装饰的函数的参数 6 '''在被装饰函数之前要做的事''' 7 param02(param03) 8 '''在被装饰函数之前要做的事''' 9 print("inner func") 10 11 print("outer func") 12 return inner 13 14 print("wrapper") 15 return outer
三、作业
1、编写装饰器,为多个函数加上认证的功能(用户的账号密码来源于文件),要求登录成功一次,后续的函数都无需再输入用户名和密码。

1 FLAG = False 2 def login(func): 3 def inner(*args,**kwargs): 4 global FLAG 5 '''登录程序''' 6 if FLAG: 7 ret = func(*args, **kwargs) # func是被装饰的函数 8 return ret 9 else: 10 username = input('username : ') 11 password = input('password : ') 12 if username == 'boss_gold' and password == '22222': 13 FLAG = True 14 ret = func(*args,**kwargs) #func是被装饰的函数 15 return ret 16 else: 17 print('登录失败') 18 return inner 19 20 @login 21 def shoplist_add(): 22 print('增加一件物品') 23 24 @login 25 def shoplist_del(): 26 print('删除一件物品') 27 28 shoplist_add() 29 shoplist_del()
2、编写装饰器,为多个函数加上记录调用功能,要求每次调用函数都将被调用的函数名称写入文件。

1 def log(func): 2 def inner(*args,**kwargs): 3 with open('log','a',encoding='utf-8') as f: 4 f.write(func.__name__+'\n') 5 ret = func(*args,**kwargs) 6 return ret 7 return inner 8 9 @log 10 def shoplist_add(): 11 print('增加一件物品') 12 13 @log 14 def shoplist_del(): 15 print('删除一件物品') 16 17 shoplist_add() 18 shoplist_del() 19 shoplist_del() 20 shoplist_del() 21 shoplist_del() 22 shoplist_del()
3、进阶作业(选做):
编写下载网页内容的函数,要求功能是:用户传入一个url,函数返回下载页面的结果
编写装饰器,实现缓存网页内容的功能:
具体:实现下载的页面存放于文件中,如果文件内有值(文件大小不为0),就优先从文件中读取网页内容,否则,就去下载,然后存到文件中

1 import os 2 from urllib.request import urlopen 3 def cache(func): 4 def inner(*args,**kwargs): 5 if os.path.getsize('web_cache'): 6 with open('web_cache','rb') as f: 7 return f.read() 8 ret = func(*args,**kwargs) #get() 9 with open('web_cache','wb') as f: 10 f.write(b'*********'+ret) 11 return ret 12 return inner 13 14 @cache 15 def get(url): 16 code = urlopen(url).read() 17 return code 18 19 20 # {'网址':"文件名"} 21 ret = get('http://www.baidu.com') 22 print(ret) 23 ret = get('http://www.baidu.com') 24 print(ret) 25 ret = get('http://www.baidu.com') 26 print(ret)