Python中的上下文管理器怎么创建
这篇文章主要讲解了"Python中的上下文管理器怎么创建",文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习"Python中的上下文管理器怎么创建"吧!
通常我们希望把一些操作放到一个代码块中,在代码块中执行时就可以保持在某种运行状态,而当离开该代码块时就执行另一个操作,结束当前状态;所以,简单来说,上下文管理器的目的就是规定对象的使用范围,如果超出范围就采取"处理"。Python提供了不同的方法来管理执行时间。例如,您可以使用Python的内置timeit模块来管理一小段代码的执行时间。
>>> import timeit
>>> timeit.timeit('"-".join(str(n) for n in range(100))', number=10000)
0.3018611848820001
但是,timeit.timeit
函数仅接受字符串,如果要管理比较复杂的函数时会有局限性。以下示例向您展示如何使用timeit
模块运行和管理函数。
def test():
"""Stupid test function"""
L = [i for i in range(100)]
if __name__ == '__main__':
import timeit
print(timeit.timeit("test()", setup="from __main__ import test"))
尽管它可以工作,但看起来并不是真正的pythonic。管理执行时间的另一种方法是利用Python的内置cProfile
模块,但是并不建议用它,实际上它不是很精确,这只是一种变通方法,可让您了解某些代码段需要执行多长时间。您可以通过以下方式使用它:
>>> python -m cProfile <file_name.py>
既然上面的两种方法都不是非常Pythonic并且都有缺陷,那么我们如何实现一个比较完美的解决方案呢?
其实很简单:我们只要能拿到程序开始执行和结束执行的时间就可以了,下面介绍具体方法,Python有一个内置模块可供我们使用:time
。
>>> import time
>>> start = time.time()
>>> # do some stuff
>>> end = time.time()
>>> print(f"Elapsed Time: {end - start}")
但是这样写不是很方便。我们可以创建一个上下文管理器。
创建一个上下文管理器
使用Python创建上下文管理器有两种不同方法,我们将研究两种方法来实现此目的:基于类和基于生成器的上下文管理器。
基于类的上下文管理器
要创建基于类的上下文管理器,需要先实现魔法变量__enter__
和__exit__
。进入上下文(或代码块)时调用第一个,离开上下文时调用后者。
有了这些准备,我们就可以来创建一个实现这两种方法的Timer
类。进入代码块时,我们希望获取当前时间并将其保存到表示开始的变量中。如果我们离开代码块,我们想获取当前时间并从中减去开始时间。结果被打印出来。
为了自定义输出,我们让用户指定一个语句,该语句在经过的时间之前打印。以下要点向您展示了一个即用型的类。
from time import time
class Timer(object):
def __init__(self, description):
self.description = description
def __enter__(self):
self.start = time()
def __exit__(self, type, value, traceback):
self.end = time()
print(f"{self.description}: {self.end - self.start}")
with Timer("List Comprehension Example"):
s = [x for x in range(10_000_000)]
基于生成器的上下文管理器
基于生成器的方法更加简单。我们可以创建一个包含程序流程的生成器函数(获取开始和结束时间以及打印经过的时间)。@contextmanager
装饰器通过使用GeneratorContextManager
对象包装生成器,将生成器功能转换为适当的上下文管理器。
from contextlib import contextmanager
from time import time
@contextmanager
def timing(description: str) -> None:
start = time()
yield
ellapsed_time = time() - start
print(f"{description}: {ellapsed_time}")
with timing("List Comprehension Example"):
s = [x for x in range(10_000_000)]
如果执行了with
后面的代码块,将跳回到yield关键字之后的位置继续执行。感谢各位的阅读,以上就是"Python中的上下文管理器怎么创建"的内容了,经过本文的学习后,相信大家对Python中的上下文管理器怎么创建这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是,小编将为大家推送更多相关知识点的文章,欢迎关注!