# 装饰器的进阶
# 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 '好开心' ret = holiday(3) print(ret) ''' 在此添加调用前代码 全体放假 3 天 在此添加调用后代码 好开心 '''
def outer(*args,**kwargs): print(args) #(1, 2, 3, 4) print(*args) #1 2 3 4 def inner(*args): print('inner:',args) #inner: (1, 2, 3, 4) inner(*args) outer(1,2,3,4) #或 outer(*[1,2,3,4]) #或 outer(*(1,2,3,4))
def wahaha(): ''' 一个打印娃哈哈的函数 :return: ''' print('娃哈哈') print(wahaha.__name__) #查看函数名 wahaha print(wahaha.__doc__) #查看注释文档
#带参数的装饰器
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): ''' 这是一个放假通知 :param day: :return: ''' print('全体放假 %s 天' % day) return '好开心' ret = holiday(3) print(ret) print(holiday.__name__) #holiday print(holiday.__doc__) # 这是一个放假通知 # :param # day: # :return:
# 1、编写装饰器,为多个函数加上认证的功能(用户的账号密码来源于文件),
# 要求登录成功一次,后续的函数都无需再输入用户名和密码
FLAG = False def login(func): def inner(*args,**kwargs): global FLAG '''登录程序''' if FLAG: ret = func(*args, **kwargs) # func是被装饰的函数 return ret else: username = input('username : ') password = input('password : ') if username == 'boss_gold' and password == '22222': FLAG = True ret = func(*args,**kwargs) #func是被装饰的函数 return ret else: print('登录失败') return inner @login def shoplist_add(): print('增加一件物品') @login def shoplist_del(): print('删除一件物品') shoplist_add() shoplist_del()
# 2、编写装饰器,为多个函数加上记录调用功能,要求每次调用函数都将被调用的函数名称
# 写入文件
def log(func): def inner(*args,**kwargs): with open('log','a',encoding='utf-8') as f: f.write(func.__name__+'\n') ret = func(*args,**kwargs) return ret return inner @log def shoplist_add(): print('增加一件物品') @log def shoplist_del(): print('删除一件物品') shoplist_add() shoplist_del() shoplist_del() shoplist_del() shoplist_del() shoplist_del()
# 进阶作业:
# 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) #get() 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('http://www.baidu.com') print(ret) ret = get('http://www.baidu.com') print(ret) ret = get('http://www.baidu.com') print(ret)
#带参数的装饰器
#500个函数
import time FLAGE = False def timmer_out(flag): def timmer(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 # timmer = timmer_out(FLAGE) @timmer_out(FLAGE) #wahaha = timmer(wahaha) def wahaha(): time.sleep(0.1) print('wahahahahahaha') @timmer_out(FLAGE) def erguotou(): time.sleep(0.1) print('erguotoutoutou') wahaha() erguotou()
#多个装饰器装饰一个函数
def wrapper1(func): def inner1(): print('wrapper1 ,before func') ret = func() print('wrapper1 ,after func') return ret return inner1 def wrapper2(func): def inner2(): print('wrapper2 ,before func') ret = func() print('wrapper2 ,after func') return ret return inner2 def wrapper3(func): def inner3(): print('wrapper3 ,before func') ret = func() print('wrapper3 ,after func') return ret return inner3 @wrapper3 @wrapper2 @wrapper1 def f(): print('in f') return '哈哈哈' print(f())