1

Python 的with exp() as obj:语法对任何具有“强制”进入和退出方法的对象都很有吸引力——考虑到人们尝试扩展obj.__del__但结果不佳的情况以及所有这些情况,它似乎指向使用__enter__and__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的替代品,而我不断发现的一件事是 Python 社区喜欢知道在实现某个功能时会发生什么。所以如果用错误的咒语来解决正确的问题,它仍然是错误的答案。try/finallyyield

Python 是否with...as出于特定原因故意为生成器保留语法,或者是否可以根据需要应用此语法?如果有目的,那目的是什么?(我在 PEP 8 中几乎没有提到with/as,如果那是正确的地方看的话)

4

1 回答 1

1

你好像误会了什么。

[我]似乎人们通常将 XXX 视为 YYY 语法来替代 try/finally 子句和/或 yield 语句

不,一个没有。每当您需要管理上下文时,都可以使用上下文管理器。你的用例很好。

使用上下文管理器替换try.. finallyuse 是一个用例。我不确定您从哪里得到有关生成器的想法;也许是因为有用的@contextlib.contextmanager()装饰器可以让您将生成器变成上下文管理器,从而简化创建上下文管理器。

我至少能想到 Python 标准库中的两个反例:

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

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

这些不是try..finally处理程序的替代品,尽管您可以想象使用..和添加的线程安全层为decimal上下文获得相同的功能;然而,这将是更多的工作。tryfinally

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

于 2014-07-15T17:53:15.123 回答