13

次のセマンティクスをサポートするコードを作成しようとしています。

with scope('action_name') as s:
  do_something()
  ...
do_some_other_stuff()

スコープ、とりわけ (セットアップ、クリーンアップ) は、このセクションを実行するかどうかを決定する必要があります。
たとえば、ユーザーが 'action_name' をバイパスするようにプログラムを構成した場合、Scope() が評価された後、最初に do_something() を呼び出さずに do_some_other_stuff() が実行されます。
私はこのコンテキストマネージャーを使用してそれをやろうとしました:

@contextmanager
def scope(action):
  if action != 'bypass':
    yield

しかし、RuntimeError: generator didn't yield例外が発生しました(actionの場合'bypass')。
より冗長なオプションの実装に戻ることなく、これをサポートする方法を探しています。

with scope('action_name') as s:
  if s.should_run():
    do_something()
    ...
do_some_other_stuff()

どうすればこれを達成できるか知っている人はいますか?
ありがとう!

PS私はpython2.7を使用しています

編集:解決策は必ずしもステートメント
に依存する必要はありません。withそれなしでそれを表現する方法を正確に知りませんでした。本質的には、コンテキストの形式 (含まれるロジックとは関係なく、セットアップと自動クリーンアップをサポートする) が必要であり、setup メソッドに渡され、構成で選択されたパラメーターに基づいて条件付き実行を可能にします。
また、デコレータを使用して可能な解決策についても考えました。例:

@scope('action_name') # if 'action_name' in allowed actions, do:
                      #   setup()
                      #   do_action_name()
                      #   cleanup()
                      # otherwise return
def do_action_name()
  do_something()

しかし、これらのスコープに基づいて内部構造 (つまり、コードを関数に分割する方法) をあまり強制したくありません。
クリエイティブなアイデアを持っている人はいますか?

4

4 に答える 4

7

基本的な言語構造の予想される動作を変更しようとしています。それは決して良い考えではありません。混乱を招くだけです。

回避策に問題はありませんが、少しだけ単純化できます。

@contextmanager 
def scope(action): 
  yield action != 'bypass'

with scope('action_name') as s: 
  if s: 
    do_something() 
    ... 
do_some_other_stuff() 

代わりに、メソッドが有用なオブジェクトを返すか、同じ方法で使用されるクラスscopeにすることができます。__enter__None

于 2010-11-30T22:23:41.373 に答える
4

以下はうまくいくようです:

from contextlib import contextmanager

@contextmanager
def skippable():
    try:
        yield
    except RuntimeError as e:
        if e.message != "generator didn't yield":
            raise

@contextmanager
def context_if_condition():
    if False:
        yield True

with skippable(), context_if_condition() as ctx:
    print "won't run"

考慮事項:

  • 誰かがより良い名前を考え出す必要があります
  • context_if_conditionなしでは使用できませんがskippable、それを強制する/冗長性を削除する方法はありません
  • 意図したよりも深い関数から RuntimeError をキャッチして抑制する可能性があります (カスタム例外はそこで役立つ可能性がありますが、それは全体の構成をさらに混乱させます)
  • @Mark Ransomのバージョンを使用するよりも明確ではありません
于 2016-10-29T12:17:51.147 に答える
1

これはできないと思います。コンテキストマネージャーをクラスとして実装しようとしましたが、ブロックに例外を発生させる方法はありません。例外は、後でメソッドによってスケルチされます__exit__()

于 2010-11-30T14:19:45.287 に答える
-2

私はあなたと同じユースケースを持っており、あなたが質問を投稿してから誰かが有益に開発した条件付きライブラリに出くわしました。

サイトから、その使用法は次のとおりです。

with conditional(CONDITION, CONTEXTMANAGER()):
    BODY()
于 2014-12-11T16:08:47.477 に答える