2

次のようなコードがあります。

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

このコードを次のように動作させたい:

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

else ブロック内のステートメントも、args へのアクセスが必要になります。

f1しかし、私はこの抽象化のユーザーから隠したいsome_conditionので、if-else ブロックを使用することはできません。また、関数内のすべてのステートメントをラップするようにユーザーに制約を課したくありません。withこれを可能にするコンテキストでPythonの魔法を行うことは可能ですか?

4

2 に答える 2

3

私が得ることができる最も近いものは、次のような 2 つのネストされたコンテキスト マネージャーを使用することです。

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をキャッチします。SkippedExceptionSomeContextarg == 1

複数のコンテキスト式の構文は、Python 2.7 以降でのみサポートされていることに注意してください。以前のバージョンでは、次のように記述する必要がありました。

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

ドキュメントの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 に答える