1装饰器
#装饰器的进阶 #functools.wraps #带参数的装饰器 #多个装饰器装饰同一个函数 #装饰器: #本质:闭包函数 #原则:开放封闭 #作用:不改变原函数的调用方式的情况下 在函数的前后添加功能 #装饰器 def wrapper(func): def inner(*args,**kwargs): print('在被装饰的函数执行之前要做的事') ret=func(*args,**kwargs) print('在被装饰的函数执行之后要做的事') return ret return inner @wrapper def holiday(day): print("全体放假%s天" % day) return "很开心" print(holiday(3)) <<< 在被装饰的函数执行之前要做的事 全体放假3天 在被装饰的函数执行之后要做的事 很开心
*的聚合打散
#接收的时候聚合 执行的时候打散 def outer(*args): print(args) print(*args) def inner(*args): print("inner:",args) inner(*args) outer(1,2,3,4)#==outer(*[1,2,3,4])==outer(*(1,2,3,4)) (1, 2, 3, 4) 1 2 3 4 inner: (1, 2, 3, 4)
2.完美装饰器
# 2 完美装饰器 from functools import wraps def wrapper(func): @wraps(func) def inner(*args,**kwargs): print('在被装饰的函数执行之前要做的事') ret=func(*args,**kwargs) print('在被装饰的函数执行之后要做的事') return ret return inner @wrapper def holiday(day): '''这是一个放假的通知''' print("全体放假%s天" % day) return "很开心" print(holiday(3)) print(holiday.__name__) #打印函数的名字 print(holiday.__doc__) #打印函数的字符串注释 <<< 在被装饰的函数执行之前要做的事 全体放假3天 在被装饰的函数执行之后要做的事 很开心 holiday 这是一个放假的通知
def wahaha(): ''' 一个打印娃哈哈的函数 ''' print('wahha') print(wahaha.__name__) #查看字符串格式的函数名 print(wahaha.__doc__) #document 查看字符串格式的注释 wahaha() <<< wahaha 一个打印娃哈哈的函数 wahha
3.作业
#1.编写一个装饰器 为多个函数加上认证功能(用户的账号密码来源于文件) #要求登陆成功一次 后续的函数都无需再输入用户名和密码 FLAG=False def login(func): def inner(*args,**kwargs): global FLAG if FLAG: ret=func(*args,**kwargs) return ret else: username=input('username:') password=input('password:') if username=='hhh'and password=='123': FLAG=True ret = func(*args, **kwargs) return ret else: print('登录失败') return inner @login def shoplist(): print('增加一件物品') @login def shoplist_remove(): print('删除一件物品') shoplist() shoplist_remove() <<< username:hhh password:123 增加一件物品 删除一件物品
#2 编写装饰器 为多个函数加上记录调用功能 要求每次调用函数都将被调用的函数名称写入文件 def log(func): def inner(*args,**kwargs): with open('log','a',encoding='utf-8')as f: f.write(func.__name__+' ') ret=func(*args,**kwargs) return ret return inner @log def shoplist(): print('增加一件物品') @log def shoplist_remove(): print('删除一件物品') return 'shanchu' shoplist_remove() shoplist() # shoplist_remove() print(shoplist_remove()) <<< 删除一件物品 增加一件物品 删除一件物品 shanchu
#1.编写下载网页内容的函数 要求功能是:用户传入一个人url,函数返回下载页面的结果 #2.为题目1编写装饰器 实现缓存网页内容的功能: #具体:实现下载的页面放入文件中,如果文件内有值(文件大小不为0),就优先从文件中读取网页内容 #否则就去下载存到文件中 # import os from urllib.request import urlopen def cache(func): def inner(*args,**kwargs): if os.path.getsize('web_cache'): with open('web_cache','rb') as f: return f.read() ret=func(*args,**kwargs) with open('web_cache','wb')as f: f.write(b'****'+ret) return ret return inner @cache def get(url): code=urlopen(url).read() return code ret=get('https://www.baidu.com/') print(ret) ret1=get('https://www.baidu.com/') print(ret1) ret=get('https://ilovefishc.com/html5/') print(ret) <<< b'<html> <head> <script> location.replace(location.href.replace("https://","http://")); </script> </head> <body> <noscript><meta http-equiv="refresh" content="0;url=http://www.baidu.com/"></noscript> </body> </html>' b'****<html> <head> <script> location.replace(location.href.replace("https://","http://")); </script> </head> <body> <noscript><meta http-equiv="refresh" content="0;url=http://www.baidu.com/"></noscript> </body> </html>' b'****<html> <head> <script> location.replace(location.href.replace("https://","http://")); </script> </head> <body> <noscript><meta http-equiv="refresh" content="0;url=http://www.baidu.com/"></noscript> </body> </html>'
4.装饰器的进阶
1.带参数的装饰器
#4 装饰器进阶 #1 带参数的装饰器 #500个函数 import time FLAGE=False def timmer_out(flag): def timmer_out(func): def inner(*args,**kwargs): if flag: start=time.time() ret=func(*args,**kwargs) end=time.time() print(end-start) return ret else: ret = func(*args, **kwargs) return ret return inner return timmer_out @timmer_out(FLAGE) def wahaha(): time.sleep(1) print("wahahaha") @timmer_out(' ') def er(): time.sleep(1) print("222222") wahaha() er() <<< wahahaha 222222 1.0006272792816162
2.多个装饰器装饰同一个函数
#2 多个装饰器装饰一个函数 def wrapper1(func): def inner(*args,**kwargs): print("wrapper1 before func") ret=func(*args,**kwargs) print("wrapper1 after func") return ret return inner def wrapper2(func): def inner(*args,**kwargs): print("wrapper2 before func") ret=func(*args,**kwargs) print("wrapper2 after func") return ret return inner def wrapper3(func): def inner(*args,**kwargs): print("wrapper3 before func") ret=func(*args,**kwargs) print("wrapper3 after func") return ret return inner @wrapper1 @wrapper2 @wrapper3 def f(): print('in f') return "hhh" print(f()) <<< wrapper1 before func wrapper2 before func wrapper3 before func in f wrapper3 after func wrapper2 after func wrapper1 after func hhh