生成器可以通过上下文管理器内部的yield‘管理资源来管理资源。一旦调用生成器的close()方法(或引发异常),资源就会被释放。
由于最后忘记调用close()很容易,我认为显然也要使用上下文管理器(以及处理潜在的异常)。我知道我可以使用contextlib.closing,但是直接在with语句中使用生成器不是更好吗?
为什么生成器不应该是上下文管理器?
发布于 2014-06-03 18:05:13
一般来说,你没有看到更多的生成器作为上下文管理器,而visa相反的原因是,它们的目标是解决不同的问题。上下文管理器之所以出现,是因为它为资源提供了一种简洁的定义可执行代码范围的方法。
有一个非常好的理由,您可能希望将实现__iter__()的类与作为上下文管理器的类分离,这就是单一责任原则。单一责任归结为概念。
做一门课,做一件事,把它做好
列表是可迭代的,但这是因为它们是一个集合。他们只管理他们持有的状态,迭代只是访问该状态的另一种方式。除非您需要迭代作为访问包含对象的状态的一种方法,否则我看不到将两者混合和匹配的理由。即使那样,我也会不遗余力地用真正的OO风格把它分开。
发布于 2014-06-03 19:20:26
就像Wheaties说的,你想让课程只做“一件事,并且做得好”。特别是在上下文管理器中,他们正在管理上下文。所以问问你自己,这里的背景是什么?大多数情况下,它将拥有一个开放的资源。不久前,我询问了using a queue with a context manager的情况,响应基本上是,队列作为上下文没有意义。然而,“在一个任务中”是我所处的真正的上下文,为此做一个上下文管理器是有意义的。
此外,没有迭代的with语句。例如,我不能在这样的语句中打开文件并遍历它:
for line in file with open(filename) as file:
...必须分两行进行:
with open(filename) as file:
for line in file:
...这很好,因为所管理的上下文不是“我们正在迭代文件”,而是“我们打开了一个文件”。那么,上下文又是什么呢?你到底在做什么?最有可能的是,您的托管上下文实际上不是通过资源进行的迭代。但是,如果您查看特定的问题,您可能会发现确实存在生成器正在管理上下文的情况。希望了解上下文是什么,应该给您一些关于如何适当管理它的想法。
https://stackoverflow.com/questions/24021648
复制相似问题