2

我有一些这样的代码:

with SomeContext(args):
  <statement1>
  .
  .
  <statementN>

我希望这段代码的行为如下:

if some_condition(args):
  f1()
else:
  <statement1>
  .
  .
  <statementN>

else 块中的语句也需要访问 args。

但是我想隐藏这个抽象f1some_condition用户,所以使用 if-else 块是不可行的。此外,我不想强​​制用户约束将所有语句包装在一个函数中。with是否可以在允许这样做的上下文中做一些 python 魔术?

4

2 回答 2

3

我能得到的最接近的是使用两个嵌套的上下文管理器,如下所示:

class SkippedException(Exception):
    pass

class SkipContext:
    def __enter__(self):
        pass
    def __exit__(self, type, value, tb):
        return type is SkippedException

class SomeContext:
    def __init__(self, arg):
        self.arg = arg
    def __enter__(self):
        if self.arg == 1:
            print "arg", self.arg
            raise SkippedException()
    def __exit__(self, type, value, tb):
        pass

with SkipContext(), SomeContext(1):
    print "body"

SkipContext经理基本上抓住了SkippedException内部经理提出的SomeContext情况arg == 1

请注意,多个上下文表达式的语法仅在 Python 2.7 或更高版本中受支持。在早期版本中,您必须编写:

with SkipContext():
    with SomeContext(1):
        print "body"

上下文管理器,尽管文档中有声明,但当从 within 抛出异常时,它contextlib.nested与上述嵌套语句的语义并不完全匹配,因此在这种情况下它不起作用。with__enter__

应该注意的是,PEP 343提到不鼓励隐藏流控制的宏(如上下文管理器),并引用Raymond Chen 对隐藏流控制的咆哮

于 2012-12-05T21:59:32.817 回答
-2

是的,您可以轻松地创建这样的上下文管理器,如下所示。

import contextlib

@contextlib.contextmanager
def SomeContext(args):
    if some_condition(args):
        f1()
    else:
        yield

用户的包装代码在yield. 我认为上下文管理器有时不执行用户的代码不是问题,但我没有检查过。

于 2012-11-30T05:39:24.000 回答