-1

让我们看看这个例子:

with mycontextmanager(arg1='value', arg2=False):
    print 'Executed'

有没有办法在基于参数的上下文管理器中执行代码块( ),例如:当 arg2 不为 False 时?print 'Executed'

4

2 回答 2

1

另一种选择是使用特殊的ConditionalExecution上下文管理器,其__enter__方法返回有条件地引发SkipExecution异常的操作。该__exit__方法仅抑制此异常。类似于以下内容:

class SkipExecution(Exception): pass

class ConditionalExecution(object):
    def __init__(self, value, arg):
        self.value = value
        self.arg = arg
    def __enter__(self):
        def action():
            if not self.arg:
                raise SkipExecution()
        return action
    def __exit__(self, exc_type, exc_value, tb):
        if exc_type is SkipExecution:
            return True
        return False

用作:

In [17]: with ConditionalExecution(1, True) as check_execution:
    ...:     check_execution()
    ...:     print('Hello')
    ...:     
Hello

In [18]: with ConditionalExecution(1, False) as check_execution:
    ...:     check_execution()
    ...:     print('Hello')

In [19]: 

但是问题是您必须添加对返回值的调用。

问题是当且仅当__exit__成功返回时才调用它,这意味着您不能引发异常来阻止代码块的执行。如果您愿意,您可以修改此解决方案,以便可以在第一行完成调用,例如: __enter____enter__check_execution()

In [29]: with ConditionalExecution(1, True) as check_execution, check_execution():
    ...:     print('Hello')
Hello

In [30]: with ConditionalExecution(1, False) as check_execution, check_execution():
    ...:     print('Hello')

使用Skipper帮助上下文管理器:

class SkipExecution(Exception): pass

class Skipper(object):
    def __init__(self, func):
        self.func = func
    def __call__(self):
        return self.func() or self
    def __enter__(self):
        return self
    def __exit__(self, *args):
        pass

class ConditionalExecution(object):
    def __init__(self, value, arg):
        self.value = value
        self.arg = arg
    def __enter__(self):
        def action():
            if not self.arg:
                raise SkipExecution()
        return Skipper(action)
    def __exit__(self, exc_type, exc_value, tb):
        if exc_type is SkipExecution:
            return True
        return False

我认为没有至少像上面的示例中那样的显式函数调用,无论如何都无法做到这一点。

于 2014-03-30T12:45:30.807 回答
0

也许像这样,假设您的上下文管理器支持“任何”属性,该属性会在初始化时公开它在 arg2 中获得的值:

with mycontextmanager(arg1='value', arg2=False) as ctx:
    if ctx.whatever:
        print 'Executed'
于 2014-03-30T11:58:12.227 回答