上下文管理器是严格的发电机?

时间:2014-07-15 17:48:36

标签: python contextmanager

Python的with exp() as obj:语法对任何具有强制性'的对象都很有吸引力。进入和退出方法 - 考虑到人们尝试延长obj.__del__但结果不佳的情况,这似乎指向使用__enter____exit__方法的方法。

我想到的第一件事是具有进入和退出方法的状态机;无论如何都要处理的事情,但使状态机的实际实现变得非常简单。

class State(object):
    def __init__(self, strategy):
        self.strategy = strategy

    def __enter__(self, *args):
        return self

    def __call__(self, *args, **kwargs):
        self.strategy(self, *args, **kwargs)

    def __exit__(self, *args):
        clean_up_things()

...
...
...
def state_handle():
    states = (State(foo), State(bar), State(eggs))
    for state in states:
        with state() as s:
            what_ever(s)

然而,似乎人们通常会将with XXX as YYY语法视为try/finally子句和/或yield语句的替代,我不断发现的一件事是Python社区喜欢知道实现某个功能时会发生什么。因此,如果使用错误的法术来解决正确的问题,那么它仍然是错误的答案。

由于特定原因,Python是否故意为生成器保留with...as语法,或者可以按照人们认为合适的方式应用此语法?如果有目的,那么目的是什么? (我在PEP 8中看到了很少甚至没有提到with/as,如果这样的话甚至是正确的地方)

1 个答案:

答案 0 :(得分:1)

你似乎误解了一些东西。

  

[我]似乎通常会将XXX视为YYY语法,以替换try / finally子句和/或yield语句

不,一个人没有。无论何时需要管理上下文,都可以使用上下文管理器。你的用例很好。

使用上下文管理器替换try .. finally使用一个用例。我不确定你从哪里得到关于发电机的想法;也许是因为有用的@contextlib.contextmanager() decorator允许您将生成器转换为上下文管理器,从而简化了创建上下文管理器的过程。

我可以想到Python标准库中至少有两个反例:

  • unittest;使用assertRaises作为上下文管理器可以引发异常,然后测试异常的各个方面。

  • decimal; localcontext管理十进制数精度,舍入和其他方面。

这些不是try .. finally处理程序的替代品,但您可以设想decimal上下文与try相同的功能。{{1}和一个增加的线程安全层;然而,这将是一项更多的工作。

最初的Python增强建议可能会让您感兴趣:http://www.python.org/dev/peps/pep-0343/