装饰器进阶
@*arg:接收就是元组,调用就是打散
1.wraps内部装饰器的使用
from functools import wraps
def wahaha():
'''
一个函数
'''
print('哇哈哈')
print(wahaha.__name__) #获取函数内的打印中的字符串
print(wahaha.__doc__) #获取函数内的注释字符串
2.装饰器内部wraps的使用(可在带装饰器的函数中获取打印的字符串和注释的字符串)
from functools import wraps
functools.wraps
from functools import wraps
def timer(f):
@wraps(f)
def inner(*args,**kwargs):
'''在被装饰函数之前要做的事'''
ret = f(*args,**kwargs)
'''在被装饰函数之后要做的事'''
return ret
return inner#5
@timer
def func(a,b):#2
time.sleep(0.01)#9
print('大家好!',a,b)#10
return '新年好'
print(func.__name__)
3.带参数的装饰器(如果FLAG为真就执行装饰内容,反之不执行)
import time
FLAGE = False #用于判断需不需要执行装饰的内容
def timmer_out(flag):#1
def timmer(func):
def inner(*arg,**karg):#5
if flag:
start = time.time()
ret = func(*arg,**karg)
end = time.time()
print(end - start)
return ret
else:
ret = func(*arg, **karg)
return ret
return inner
return timmer
@timmer_out(FLAGE) #timmer = timer_out(FLAGE)(#2) @timmer == (wahaha = timmer(wahaha))(#3)
def wahaha():
time.sleep(0.1)
print('wahahahah')
@timmer_out(FLAGE)
def erguotou():
time.sleep(0.01)
print('nihaoya')
wahaha()#4
erguotou()
4.多个装饰器装饰同一个函数
def wrapper1(f): #1
def inner1(): #8
print(‘wrapper1,befor’) #9
ret = f()
print(‘wrapper1,after’) #11
return ret
return inner1 #f–>func
def wrapper2(f): #f-->inner1 #2
def inner2(): #6
print('wrapper2,befor') #7
ret = f()
print('wrapper2,after') #12
return ret
return inner2
@wrapper2 #func = wrapper2(func)-->wrapper2(inner1)==inner2 #4
@wrapper1 #func = wrapper1(func) --> inner1 #3
def func(): #找最近的装饰符
print('你好鸭!') #10
return '好的' #13
print(func()) #==>inerr2() #5
输出结果:
wrapper2,befor
wrapper1,befor
你好鸭!
wrapper1,after
wrapper2,after
好的
作业:
1.编写装饰器,为多个函数加上认证的功能(用户的账号密码来源于文件),要求登录成功一次,后续的函数都无需再输入用户名和密码
flag = False
def login(func):
def inner(*arg,**karg):
global flag
'''登陆程序'''
if flag:
ret = func(*arg,**karg)
return ret
else:
username = input('username:')
password = input('password:')
if username == 'boss_gold' and password == '222':
flag = True
ret = func(*arg,**karg)
else:
print('登陆失败!')
return inner
@login
def wrapper():
print('增加一件物品')
@login
def shoplist_add():
print('删除一件物品')
wrapper()
shoplist_add()
2.编写装饰器,为多个函数加上记录调用功能,要求每次调用函数都将被调用的函数名称写入文件
def log(func):
def inner(*arg,**karg):
with open('log','a',encoding='utf-8') as f:
f.write(func.__name__+'\n')
reg = func(*arg,**karg)
return reg
return inner
@log
def wrapper():
print('增加一件物品')
@log
def shoplist_add():
print('删除一件物品')
wrapper()
进阶作业(选做):
1.编写下载网页内容的函数, 要求功能是:用户传入一个u1,函数返回下载页面的结果
2.为题目1编写装饰器,实现缓存网页内容的功能
具体:实现下载的页面存放于文件 中,如果文件内有值(文件大小不为0),就优先从文件中读取网页内容,否则,就去下载,然后
from urllib.request import urlopen
import os
def cache(func):
def inner(*arg,**karg):
if os.path.getsize('web_cath'): #查看文件是否为空
with open('web_cath','rb') as f:
return f.read()
ret = func(*arg,**karg) #请求网页
with open('web_cath','wb') as f:
f.write(b'***'+ret) #将请求的结果写到文件里
return ret
return inner
@cache
def get(url):
html = urlopen(url).read()
return html
ret = get('http://www.baidu.com')
print(ret)
ret = get('http://www.baidu.com')
print(ret)
ret = get('http://www.baidu.com')
print(ret)