-1

この例を見てみましょう:

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

引数に基づいてコンテキスト マネージャ内でコード ブロック () を実行しない方法はありますか? たとえば、arg2 が False でない場合は?print 'Executed'

4

2 に答える 2

1

もう 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 で取得した値を公開する "whatever" プロパティをサポートしていると仮定します。

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