简体   繁体   English

如何停止 Python 中的语句执行?

[英]How to stop statements within a Python with context from executing?

I've some code like this:我有一些这样的代码:

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

I want this code to behave like this:我希望这段代码的行为如下:

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

Statements in else block will also need an access to args. else 块中的语句也需要访问 args。

But I want to hide f1 and some_condition from user of this abstraction, so using an if-else block is out of option.但是我想对这个抽象的用户隐藏f1some_condition ,所以使用 if-else 块是不可行的。 Also I don't want to force a constraint on the user to wrap all statements in a function.此外,我不想强制限制用户将所有语句包装在 function 中。 Is it possible to do some python magic in the with context that allows this?是否可以在允许这样做with上下文中做一些 python 魔术?

The closest I can get is to use two nested context managers, something like the following:我能得到的最接近的是使用两个嵌套的上下文管理器,如下所示:

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"

The SkipContext manager essentially catches the SkippedException raised by the inner SomeContext manager in the case where arg == 1 .arg == 1的情况下, SkipContext管理器基本上捕获了内部SomeContext管理器引发的SkippedException

Note that the syntax of multiple context expressions is only supported in Python 2.7 or later.请注意,仅 Python 2.7 或更高版本支持多个上下文表达式的语法。 In earlier versions, you would have to write:在早期版本中,您必须编写:

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

The contextlib.nested context manager, despite claims in the documentation, doesn't exactly match the semantics of the above nested with statement when exceptions are thrown from within __enter__ , so it doesn't work in this case. contextlib.nested上下文管理器,尽管文档中有声明,但当从__enter__中抛出异常时,它与上述嵌套with语句的语义并不完全匹配,因此在这种情况下它不起作用。

It should be noted that PEP 343 mentions that macros (like context managers) that hide flow control should be discouraged, and referencesRaymond Chen's rant against hidden flow control .应该注意的是, PEP 343提到不鼓励隐藏流控制的宏(如上下文管理器),并引用Raymond Chen 对隐藏流控制的咆哮

Yes, you can easily create such a context manager as follows.是的,您可以轻松地创建这样的上下文管理器,如下所示。

import contextlib

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

The user's wrapped code gets executed at the point of the yield .用户的包装代码在yield点执行。 I don't think it's a problem that the context manager sometimes does not execute the user's code, but I haven't checked.我认为上下文管理器有时不执行用户的代码不是问题,但我没有检查过。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM