python 基础---装饰器

it2022-05-05  119

装饰器的本质:一个闭包函数

装饰器的功能:在不修改原函数及其调用方式的情况下对原函数功能进行扩展

装饰器的返回值:也是一个函数

1 import time 2 3 def func1(): 4 print('in func1') 5 6 def timer(func): 7 def inner(): 8 start = time.time() 9 func() 10 print(time.time() - start) 11 return inner 12 13 func1 = timer(func1) 14 func1()

语法糖

1 import time 2 def timer(func): 3 def inner(): 4 start = time.time() 5 func() 6 print(time.time() - start) 7 return inner 8 9 @timer #==> func1 = timer(func1) 10 def func1(): 11 print('in func1') 12 13 14 func1()

内包有参数

1 import time 2 def timer(func): 3 def inner(*args,**kwargs): 4 start = time.time() 5 re = func(*args,**kwargs) 6 print(time.time() - start) 7 return re 8 return inner 9 10 @timer #==> func1 = timer(func1) 11 def func1(a,b): 12 print('in func1') 13 14 @timer #==> func2 = timer(func2) 15 def func2(a): 16 print('in func2 and get a:%s'%(a)) 17 return 'fun2 over' 18 19 func1('aaaaaa','bbbbbb') 20 print(func2('aaaaaa'))

装饰器的固定格式

1 def timer(func): 2 def inner(*args,**kwargs): 3 '''执行函数之前要做的''' 4 re = func(*args,**kwargs) 5 '''执行函数之后要做的''' 6 return re 7 return inner 1 from functools import wraps 2 3 def deco(func): 4 @wraps(func) #加在最内层函数正上方 5 def wrapper(*args,**kwargs): 6 return func(*args,**kwargs) 7 return wrapper

 默写装饰器

1 装饰器默写 2 def wapper(f): # f = func5 3 def inner(*args,**kwargs): 4 print("装饰器开始") 5 ret = f(*args,**kwargs) #执行 func5(*args,**kwargs),func5(5,10) 6 print("装饰器结束") 7 return ret 8 return inner 9 10 @wapper #func5 = wapper(func5) func5 = inner 11 def func5(a,b): 12 print('本程序') 13 print(a+b) 14 return (a*b) 15 16 ret = func5(5,10) #执行func5(5,10)相当于执行inner(5,10) 17 print(ret) __doc__ __name__ 1 #再次默写装饰器函数 2 def wrapper(f): 3 def inner(*args,**kwargs): 4 pass #在装饰之前要做的事情 5 print('在装饰之前要做的事情') 6 ret = f(*args,**kwargs) 7 pass #在装饰之后要做的事情 8 print('在装饰之后要做的事情') 9 return ret 10 return inner 11 12 @wrapper #func = wrapper(func) 13 def func(day): 14 ''' 15 我只是一个函数说明 16 :param day: 17 :return: 18 ''' 19 print('我是要被装饰的函数,你能拿我咋的') 20 print('全体放假%s天'%day) 21 #print('全体放假{}天'.format(day)) 22 return '好开心' 23 24 ret = func(4) 25 print(ret) 26 27 print(func.__doc__) #查看函数的说明 28 print(func.__name__) #查看函数名 输出结果:

         在装饰之前要做的事情      我是要被装饰的函数,你能拿我咋的      全体放假4天      在装饰之后要做的事情      好开心      None       inner

wraps:使用 .__name__和 .__doc__

1 from functools import wraps 2 def wrapper(f): 3 @wraps(f) 4 def inner(*args,**kwargs): 5 pass #在装饰之前要做的事情 6 print('在装饰之前要做的事情') 7 ret = f(*args,**kwargs) 8 pass #在装饰之后要做的事情 9 print('在装饰之后要做的事情') 10 return ret 11 return inner 12 13 @wrapper #func = wrapper(func) 14 def func(day): 15 ''' 16 这是一个放假通知 17 :param day: 18 :return: 19 ''' 20 print('我是要被装饰的函数,你能拿我咋的') 21 print('全体放假%s天'%day) 22 #print('全体放假{}天'.format(day)) 23 return '好开心' 24 25 ret = func(4) 26 print(ret) 27 28 print(func.__name__) 29 print(func.__doc__)输出结果:

           在装饰之前要做的事情      我是要被装饰的函数,你能拿我咋的      全体放假4天      在装饰之后要做的事情      好开心      func

        这是一个放假通知         :param day:         :return:

题目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) # 被装饰 8 return ret 9 else: 10 username = input('username:') 11 passwd = input('passwd:') 12 if username =='boss_gold' and passwd == '222222': 13 FLAG = True 14 ret = func(*args,**kwargs)#被装饰 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()输出结果:

         username:boss_gold      passwd:222222      增加一件物品      删除一件物品

题目2:编写装饰器,为多个函数加上记录调用功能,要求每次调用函数都将被调用的函数名称写入文件

1 def log(func): 2 def inner(*args,**kwargs): 3 with open('log','a+',encoding='utf-8')as f: 4 # for line in f: 5 # print(line) 6 # print('来了吗') 7 # if line=='shoplist_add': 8 # pass 9 # else: 10 f.write(func.__name__+'\n') 11 #在装饰器函数之前所做的事情 12 ret = func(*args,**kwargs) 13 #在装饰器函数之后所做的事情 14 return ret 15 return inner 16 17 @log 18 def shoplist_add(): 19 print('增加一件物品') 20 21 @log 22 def shoplist_del(): 23 print('删除一件物品') 24 25 shoplist_del() 26 shoplist_add()输出结果:

      删除一件物品      增加一件物品

log文件内容:

     shoplist_del     shoplist_add

 题目3:

进阶作业 1.编写下载网页内容的函数,要求功能是:用户传入一个url,函数返回下载页面的结果 1 from urllib.request import urlopen 2 def get(url): 3 code = urlopen(url).read 4 return code 5 ret = get('http://www.baidu.com') 6 print(ret)结果:    返回网页下载结果 2.为题目1编写装饰器,实现缓存网页内容的功能: 具体:实现下载的页面存放于文件中,如果文件内有值(文件大小不为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'): #判断文件中是否有内容,返回的文件大小,没文件就是0 = False,第一次就是0 6 with open('web_cache','rb')as f: 7 return f.read() #如果有内容,直接return返回,不执行下面的操作 8 ret = func(*args,**kwargs) #这里执行的get() 请求网页,ret就是网页的内容 9 with open('web_cache','wb')as f: #将请求的结果写到文件里 10 f.write(b'*********'+ret) # b'*********'标识符,看是文件里面的还是网页下载的 11 return ret 12 return inner 13 14 @cache #相当于get = cache(get) 15 def get(url): 16 code = urlopen(url).read() 17 return code 18 19 ret = get('http://www.baidu.com') 20 print(ret) 21 ret = get('http://www.baidu.com') 22 print(ret) 23 ret = get('http://www.baidu.com') 24 print(ret)结果:     第一次输出是不带*********的,也就是网页下载的     第二次和第三次是带*********的,是从文件里面读取的

多个函数需要装饰给函数计算时间的装饰器

带参数的装饰器:三层

1 import time 2 FLAGE = True 3 #FLAGE = False 4 def timmer_out(FLAGE): 5 def timmer(func): 6 def inner(*args,**kwargs): 7 if FLAGE: 8 start = time.time() 9 ret = func(*args,**kwargs) 10 end = time.time() 11 print(end - start) 12 return ret 13 else: 14 ret = func(*args, **kwargs) 15 return ret 16 return inner 17 return timmer 18 19 @timmer_out(FLAGE) # timmer_out(FLAGE) = timmer @timmer :wahaha = timmer(wahaha) 20 def wahaha(): 21 time.sleep(0.1) 22 print('wahahahaha') 23 24 @timmer_out(FLAGE) 25 def erguotou(): 26 time.sleep(0.2) 27 print('erguotoutoutoutou') 28 29 wahaha() 30 erguotou()

多个装饰器装饰一个函数

1 def wrapper1(func): #func = f 2 def inner1(): 3 print('wrapper1 ,before func') 4 ret = func() #f() 5 print('wrapper1 ,after func') 6 return ret 7 return inner1 8 9 def wrapper2(func): #func = inner1 10 def inner2(): 11 print('wrapper2 ,before func') 12 ret = func() #inner1() 13 print('wrapper2 ,after func') 14 return ret 15 return inner2 16 17 @wrapper2 # f = wrapper2(f) :f = wrapper2(inner1) f = inner2 18 @wrapper1 # f = wrapper1(f) :f = inner1 19 def f(): 20 print('in f') 21 22 f() # inner2()

执行顺序

 

转载于:https://www.cnblogs.com/dzc18/p/9338647.html


最新回复(0)