Python学习日记(九) 装饰器函数
2019-08-13 08:34:06来源:博客园 阅读 ()
1.import time
a.time.time()
获取到当前的时间,返回值为浮点型
import time print(time.time()) #1565422783.6497557
b.time.sleep()
让程序执行到这个位置暂停一会
import time start = time.time() time.sleep(0.5) print('hello world!') end = time.time() print(end - start) #0.5000286102294922
2.装饰器函数
开发原则:开放封闭原则
装饰器的作用:在不改变原函数的情况下,在函数的前后添加功能
装饰器的本质:闭包函数
当想要知道一个程序执行的时间
import time start = time.time() time.sleep(0.5) print('hello world!') end = time.time() print(end - start) #0.5000286102294922
再将里面的功能单独拉出来变成一个函数
import time def func(): time.sleep(0.5) print('hello world!') def timer(func): start = time.time() func() end = time.time() print(end - start) timer(func) #hello world! #0.5000286102294922
将timer变成一个简单的装饰器
import time def func(): #被装饰的函数 time.sleep(0.5) print('hello world!') def timer(func): #装饰函数 def inner(): start = time.time() func() end = time.time() print(end - start) return inner #回传inner函数的内存地址 get_inner = timer(func) #后者得到的是inner的内存地址再赋值给get_inner get_inner() #hello world! #0.5000286102294922
执行步骤:
开放封闭原则:开放指的是对扩展开放,封闭指的是对修改封闭
语法糖:@装饰器函数名 可以替代下面的写法
装饰带一般参数且有返回值函数的装饰器
import time def wrapper(f): #装饰器函数 def inner(x): res = f(x) return res return inner @wrapper #相当于 fuc = wrapper(fuc) def fuc(var): #被装饰的函数 print(var,'Python') return False res = fuc('Hello') print(res)
装饰带万能参数的函数装饰器
import time def wrapper(f): #装饰器函数 def inner(*args,**kwargs): start = time.time() ret = f(*args,**kwargs) end = time.time() print(end - start) return ret return inner @wrapper #相当于 fuc = wrapper(fuc) def fuc(a,b,c,d,e = 5): #被装饰的函数 time.sleep(0.5) print(a,b,c,d,e) return e print(fuc(1,2,3,4,'Python'))
总结:装饰器的模板
import time def wrapper(f): def inner(*args,**kwargs): #在被装饰函数之前要做的事 res = f(*args,**kwargs) #在被装饰函数之后要做的事 return res return inner @wrapper # func = wrapper(func) def func(): #被装饰的函数 return ret = func() print(ret)
查看函数信息的方法
def fuc(var): '0123456789' print(var,'Python') return False print(fuc.__name__) #fuc 主要用于查看函数名 print(fuc.__doc__) #0123456789 主要用于查看函数的注释
我们在使用fuc()函数的时候实际上我们调用的是inner()函数,如果我们要在不修改原函数的前提下拿到原函数的信息,只需要将inner()函数变成一个装饰器:
def wrapper(f): def inner(*args,**kwargs): ret = f(*args,**kwargs) return ret return inner @wrapper def fuc(): print('Python') return True print(fuc()) print(fuc.__name__) #inner 这里调用的是inner函数
修改后:
from functools import wraps def wrapper(f): @wraps(f) def inner(*args,**kwargs): ret = f(*args,**kwargs) return ret return inner @wrapper def fuc(): print('Python') return True print(fuc()) print(fuc.__name__) #fuc 这里就改回调用的函数名是fuc
带参数的装饰器
如果许多函数都使用了同一个装饰器,那么它将需要一个布尔值作为参数来作为开关控制它们的使用
FLAGE = False def wrapper_ctrl(flag): def wrapper(fuc): def inner(*args,**kwargs): if flag: print('装饰器已开启...') ret = fuc() return ret else: print('装饰器已关闭...') return inner return wrapper @wrapper_ctrl(FLAGE) def function1(): print('aaaaaaa') @wrapper_ctrl(FLAGE) def function2(): print('bbbbbbb') @wrapper_ctrl(FLAGE) def function3(): print('ccccccc') function1() #装饰器已关闭... function2() #装饰器已关闭... function3() #装饰器已关闭...
多个装饰器装饰一个函数
def wrapper1(fuc): #2Step:fuc->f def inner1(*args,**kwargs): print('wrapper1在装饰该函数前要做的事...') #12Step:print fuc(*args,**kwargs) #13Step:这里的fuc就是f 因为第二步已经传进来了 print('wrapper1在装饰该函数后要做的事...') #15Step:print return inner1 #3Step:传回inner1 def wrapper2(fuc): #6Step:fuc->inner1 def inner2(*args,**kwargs): print('wrapper2在装饰该函数前要做的事...') #10Step:print fuc(*args,**kwargs) #11Step:这里的fuc()实际上是inner1() print('wrapper2在装饰该函数后要做的事...') #16Step:print return inner2 #7Step:返回inner2 @wrapper2 #5Step:f = wrapper2(f) 这里的f是inner1 即 f = wrapper2(inner1) #8Step:f = inner2 @wrapper1 #1Step:f = wrapper1(f) #4Step:f = inner1 #装饰器会找离它最近的函数 离这个函数最近的装饰器会先执行 def f(): print('abcdefg') #14Step:print f() #9Step:这里调用的f()实际上是inner2() '''执行结果''' # wrapper2在装饰该函数前要做的事... # wrapper1在装饰该函数前要做的事... # abcdefg # wrapper1在装饰该函数后要做的事... # wrapper2在装饰该函数后要做的事...
流程图:
3.和装饰器相关的案例
a.编写装饰器,为多个函数加上认证的功能(用户的账号密码来源于文件),要求登录成功一次,后续的函数都无需输入用户名和密码
FLAG = False def login(f): def inner(*args,**kwargs): global FLAG if FLAG: #如果已经登入成功 f(*args,**kwargs) else: username = input('请输入用户名:') password = input('请输入密码:') if username.strip() == 'JANE' and password.strip() == '123456': FLAG = True print('登入成功!') f(*args,**kwargs) else: print('登入失败!') return inner get_name('JANE') get_ID()
b.编写装饰器,为多个函数加上记录调用功能,要求每次调用函数都将把被调用的函数写入文件
def log(f): def inner(*args,**kwargs): with open('log.txt',mode = 'a',encoding='utf-8') as fileStream: fileStream.write(f.__name__ + '\n') f(*args,**kwargs) return inner @log def get_name(): print('Your username is JANE') @log def get_ID(): print('Your user ID is 110123') get_ID() get_name() get_ID()
c.编写下载网页的函数,要求功能是:用户传入一个url,函数返回下载页面的结果
from urllib.request import urlopen def get(url): html = urlopen(url).read() return html ret = get('http://www.baidu.com') print(ret) #<bound method HTTPResponse.read of <http.client.HTTPResponse object at 0x00000000073BC860>>
d.为c编写装饰器,实现缓存网页内容的功能,主要功能:实现下载的页面存放于文件中,如果文件内有值(文件大小不为0),就优先从文件中读取网页内容,否则就去下载,然后存到文件中
import os from urllib.request import urlopen def cache(func): def inner(*args,**kwargs): if os.path.getsize('web_cache'): #如果不为0 就是True 从文件中找到源码 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 end = get('http://www.baidu.com') print(end) end = get('http://www.baidu.com') print(end) end = get('http://www.baidu.com') print(end)
原文链接:https://www.cnblogs.com/Fantac/p/11332275.html
如有疑问请与原作者联系
标签:
版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有
- python3基础之“术语表(2)” 2019-08-13
- python3 之 字符串编码小结(Unicode、utf-8、gbk、gb2312等 2019-08-13
- Python3安装impala 2019-08-13
- 小白如何入门 Python 爬虫? 2019-08-13
- python_字符串方法 2019-08-13
IDC资讯: 主机资讯 注册资讯 托管资讯 vps资讯 网站建设
网站运营: 建站经验 策划盈利 搜索优化 网站推广 免费资源
网络编程: Asp.Net编程 Asp编程 Php编程 Xml编程 Access Mssql Mysql 其它
服务器技术: Web服务器 Ftp服务器 Mail服务器 Dns服务器 安全防护
软件技巧: 其它软件 Word Excel Powerpoint Ghost Vista QQ空间 QQ FlashGet 迅雷
网页制作: FrontPages Dreamweaver Javascript css photoshop fireworks Flash