55

with特定の条件下でステートメントを終了したいのですが、次のようになります。

with open(path) as f:
    print 'before condition'
    if <condition>: break #syntax error!
    print 'after condition'

もちろん、上記は機能しません。これを行う方法はありますか?(私は条件を逆にすることができることを知っています:if not <condition>: print 'after condition'-上記のような方法はありますか?)

4

13 に答える 13

83

withあなたに問題を与えますか?with問題でより多くの可能なオブジェクトを投げてください!

class fragile(object):
    class Break(Exception):
      """Break out of the with statement"""

    def __init__(self, value):
        self.value = value

    def __enter__(self):
        return self.value.__enter__()

    def __exit__(self, etype, value, traceback):
        error = self.value.__exit__(etype, value, traceback)
        if etype == self.Break:
            return True
        return error

使用する式をラップするだけwithfragileraise fragile.Breakいつでもブレークアウトできます。

with fragile(open(path)) as f:
    print 'before condition'
    if condition:
        raise fragile.Break
    print 'after condition'

この設定の利点

  • withとだけを使用しwithます。意味的に誤解を招くような1回の実行の「ループ」または狭く特殊化された関数で関数をラップしません。また、の後に余分なエラー処理を強制することもありませんwith
  • ローカル変数をラッピング関数に渡す代わりに、使用可能な状態に保ちます。
  • ネスタブル!

    with fragile(open(path1)) as f:
        with fragile(open(path2)) as g:
            print f.read()
            print g.read()
            raise fragile.Break
            print "This wont happen"
        print "This will though!"
    

    withこのように、両方を壊したい場合は、外側をラップするための新しい関数を作成する必要はありません。

  • 再構築はまったく必要ありません。すでに持っているものをラップするだけで、準備完了fragileです。

この設定の欠点

  • 実際には「break」ステートメントを使用しません。すべてに勝つことはできません;)
于 2014-05-14T21:43:07.840 に答える
48

最良の方法は、それを関数にカプセル化して使用することreturnです。

def do_it():
    with open(path) as f:
        print 'before condition'
        if <condition>:
            return
        print 'after condition'
于 2012-06-25T18:33:55.350 に答える
12

これは古くからの質問ですが、これは便利な「壊れやすいスコープ」イディオムのアプリケーションです。withステートメントを中に埋め込むだけです:

for _ in (True,):
    with open(path) as f:
        print 'before condition'
        if <condition>: break
        print 'after condition'

このイディオムは、条件付きで分割できるスコープ内にコードのブロックを含めることを唯一の目的として、常に1回だけ実行される「ループ」を作成します。OPの場合、囲まれるのはコンテキストマネージャーの呼び出しでしたが、条件付きエスケープを必要とする可能性のある、制限されたステートメントのシーケンスである可能性があります。

受け入れられた答えは問題ありませんが、この手法は関数を作成しなくても同じことを実行します。これは必ずしも便利であるとは限りません。

于 2017-05-05T03:13:51.310 に答える
9

ロジックを再構築するだけでよいと思います。

with open(path) as f:
    print 'before condition checked'
    if not <condition>:
        print 'after condition checked'
于 2012-06-25T18:47:18.480 に答える
7

breakループ内でのみ発生する可能性があるため、オプションは次のように制限されますwith

  • return( "with" +関連するステートメントを関数内に配置)
  • 終了(プログラムからの保釈-おそらく理想的ではない)
  • 例外(「with」内で例外を生成し、以下をキャッチ)

関数内でおよび関連するステートメント(および他に何も)をreturn分離できる場合、関数を使用して使用することは、おそらくここで最もクリーンで簡単なソリューションです。with

それ以外の場合は、必要に応じて内部で例外を生成し、コードの残りの部分を続行するには、withのすぐ下/外側でキャッチします。with

更新:OPが以下のコメントで示唆しているように(おそらく頬に大きなものがありますか?)、withステートメントをループ内にラップして、breakを機能させることもできますが、それは意味的に誤解を招く可能性があります。したがって、実用的なソリューションではありますが、おそらく推奨されるものではありません)。

于 2012-06-25T18:31:44.143 に答える
2
f = open("somefile","r")
for line in f.readlines():
       if somecondition: break;
f.close()

私はあなたがで抜け出すことができるとは思わない...あなたはループを使う必要がある...

[編集]または他の人が言及した関数メソッドを実行する

于 2012-06-25T18:34:53.663 に答える
2

速記スニペットとして:

class a:
    def __enter__(self):
        print 'enter'
    def __exit__(self ,type, value, traceback):
        print 'exit'

for i in [1]:
    with a():
        print("before")
        break
        print("after")

..。

enter
before
exit
于 2014-05-13T08:16:23.520 に答える
1

__exit__()この目的のための機能があります。構文は次のとおりです。

with VAR = EXPR:
  try:
    BLOCK
  finally:
    VAR.__exit__()
于 2018-03-13T20:09:13.773 に答える
1

使用while True

while True:
    with open(path) as f:
        print 'before condition'
        if <condition>: 
            break 
        print 'after condition n'
    break
于 2020-10-08T22:17:00.207 に答える
0

すべてを関数内に置くことができ、条件が真の場合はreturnを呼び出します。

于 2012-06-25T18:34:30.187 に答える
0

条件を逆にする方がおそらく便利ですが、とを使用tryしてそれを行う別の方法があります。except

class BreakOut(Exception): pass

try:
    with open(path) as f:
        print('before condition')
        if <condition>: 
            raise BreakOut #syntax error!
        print('after condition')
except BreakOut:
    pass
于 2020-11-14T12:36:22.387 に答える
0

この質問は、Python 3.4が存在する前に尋ねられましたが、3.4を使用するcontextlib.supressと、自分の個人的な例外を抑制して使用できます。

この(そのまま実行可能な)コードを確認してください

from contextlib import suppress

class InterruptWithBlock(UserWarning):
    """To be used to interrupt the march of a with"""

condition = True
with suppress(InterruptWithBlock):
    print('before condition')
    if condition: raise InterruptWithBlock()
    print('after condition')

# Will not print 'after condition` if condition is True.

したがって、質問のコードを使用すると、次のようになります。

with suppress(InterruptWithBlock) as _, open(path) as f:
    print('before condition')
    if <condition>: raise InterruptWithBlock()
    print('after condition')

注:3.4より前の場合でも、独自のsuppressコンテキストマネージャーを簡単に作成できます。

于 2021-11-05T21:20:27.973 に答える
-2

「break」から「f.close」に変更

with open(path) as f:
    print('before condition')
    if <condition>: f.close()
    print('after condition')
于 2019-12-12T04:26:57.387 に答える