补充:时间戳
import time
start_time = time.time() #time.time()时间戳:从1970年1.1到现在的秒数
time.sleep(2) #休眠两秒
end_time = time.time()
print(end_time - start_time) #结束时间减去开始时间等于运行时间
执行结果如下:
1. 闭包
1)函数里嵌套函数
def timeit():
def wrapper():
print('wrapper')
print('timeit')
timeit()
打印timeit,只执行定义的内容
2)外部函数的返回值是内部函数的引用
def timeit():
def wrapper():
print('wrapper')
print('timeit')
return wrapper
in_fun = timeit() #wrapper函数,in_fun实质上就是wrapper函数
in_fun()
执行结果如下:
3)内部函数可以使用外部函数的变量
def timeit(name):
def wrapper():
print('wrapper' + name) #name是外部函数的变量
print('timeit')
return wrapper
in_fun = timeit(name='westos')
in_fun()
执行结果如下:
2.装饰器
1、装饰器:用来装饰函数的工具。
2、在不改变源代码的情况下,添加额外功能(eg:计算运行时间,记录日志,权限判断)的工具。
3、如何实现装饰器?基于闭包。
import time
def timeit(f): # f=add
def wrapper(x,y):
start = time.time()
result = f(x,y) #f实质上是add函数,是要装饰的函数
end = time.time()
print('函数运行时间为:%.4f' %(end - start))
return result
return wrapper
@timeit # 语法糖,add=timeit(add)
def add(x,y):
return x + y
result = add(1,3)
print(result)
执行结果如下:
3.万能装饰器
import time
from functools import wraps
def timeit(f):
"""计时器的装饰器"""
@wraps(f) ##保留被装饰函数的属性信息和帮助文档
def wrapper(*args,**kwargs): # 想接受任何参数可以用(*args,**kwargs)
"""wrapper内部函数"""
start = time.time()
result = f(*args,**kwargs)
end = time.time()
print(f'函数{f.__name__}运行时间为{end - start}秒')
return result
return wrapper
@timeit
def login():
"""login desc"""
print('login..........')
login() #运行login,可以查看函数的运行时间
print(help(login)) #如果不用wraps,那么查看的就是wrapper内部函数的信息和帮助文档了
1)装饰器的万能模板
def 装饰器名称(f):
def wrapper(*args,**kwargs):
执行函数之前做的事情
result = f(*args,**kwargs)
执行函数之后做的事情
return result
return wrapper
利用做好的装饰器看一下爬一个图片需要多久:
import time
def timeit(f):
def wrapper(*args,**kwargs):
start = time.time()
result = f(*args,**kwargs)
end = time.time()
print(f'函数{f.__name__}的执行时间为{end-start}')
return result
return wrapper
@timeit
def crawl():
import requests
url = 'https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fcdn.usefulstuff.io%2F2014%2F12%2Fpython_logo.jpg&refer=http%3A%2F%2Fcdn.usefulstuff.io&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1640430605&t=06e78c1a0f656346ca4fad75591e548b'
content = requests.get(url).content
with open('venv/python.png','wb') as f: #图片,电影都是二进制文件,用wb
f.write(content)
crawl()
执行结果如下:
得到了图片:
2)含参数的装饰器
import time
def timeit(args='seconds'): ##传参
def desc(f):
def wrapper(*args,**kwargs):
start = time.time()
result = f(*args,**kwargs)
end = time.time()
if args == 'seconds':
print(f'函数{f.__name__}的执行时间为{end-start}秒')
elif args == 'minutes':
print(f'函数{f.__name__}的执行时间为{(end-start)/60}分钟')
return result
return wrapper
return desc
@timeit(args='seconds')
def login():
print('login.....')
login()
3) 多装饰器
def is_login(f):
def wrapper(*args,**kwargs):
print('is_login,用户是否登录')
result = f(*args,**kwargs)
return result
return wrapper
def is_permission(f):
def wrapper(*args,**kwargs):
print('is_permission,用户是否有权限')
result = f(*args,**kwargs)
return result
return wrapper
##规则:执行装饰器内容是从上到下,而被装饰的内容是从下到上
@is_login
@is_permission
def show_hosts():
print('显示所有云主机')
show_hosts()
执行结果如下,可以看到执行的内容是从上到下的: