我有一些像这样的代码:
with SomeContext(args):
<statement1>
.
.
<statementN>
我希望此代码的行为如下:
if some_condition(args):
f1()
else:
<statement1>
.
.
<statementN>
else块中的语句也需要访问args。
但我希望隐藏f1
和some_condition
来自此抽象的用户,因此使用if-else块是不可选的。另外,我不想强制用户使用约束来包装函数中的所有语句。是否有可能在允许这个的with
上下文中做一些python魔术?
答案 0 :(得分: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"
尽管文档中有声明,contextlib.nested
上下文管理器在with
内抛出异常时与上述嵌套__enter__
语句的语义不完全匹配,因此它不会在这种情况下工作。
应该注意PEP 343提到应该不鼓励隐藏流控制的宏(如上下文管理器),并引用Raymond Chen's rant against hidden flow control。
答案 1 :(得分:-1)
是的,您可以轻松地创建如下的上下文管理器。
import contextlib
@contextlib.contextmanager
def SomeContext(args):
if some_condition(args):
f1()
else:
yield
用户的包装代码在yield
点执行。我不认为上下文管理器有时不执行用户代码是一个问题,但我没有检查过。