25

forループ内で次のパターンが必要になる場合があります。同じループ内で複数回実行される場合があります。

try:
    # attempt to do something that may diversely fail
except Exception as e:
    logging.error(e)
    continue

今ではできないので、これを関数でラップする良い方法がわかりませんreturn continue

def attempt(x):
    try:
        raise random.choice((ValueError, IndexError, TypeError))
    except Exception as e:
        logging.error(e)
        # continue  # syntax error: continue not properly in loop
        # return continue  # invalid syntax
        return None  # this sort of works

return Noneができたよりも:

a = attempt('to do something that may diversely fail')
if not a:
    continue

しかし、それが正義だとは思いません。関数continue内からforループを(または偽造して)伝えたいのですが。attempt

4

9 に答える 9

15

Pythonには、これを実行するための非常に優れた構造がすでにあり、使用していませんcontinue

for i in range(10):
    try:
        r = 1.0 / (i % 2)
    except Exception, e:
        print(e)
    else:
        print(r)

ただし、これ以上ネストすることはありません。そうしないと、コードがすぐに非常に醜くなります。

あなたの場合、個々の関数の単体テストがはるかに簡単で、ネストされたものよりもフラットの方が優れているので、おそらくこのようなことをするでしょう:

#!/usr/bin/env python

def something_that_may_raise(i):
    return 1.0 / (i % 2)

def handle(e):
    print("Exception: " + str(e))

def do_something_with(result):
    print("No exception: " + str(result))

def wrap_process(i):
    try:
        result = something_that_may_raise(i)
    except ZeroDivisionError, e:
        handle(e)
    except OverflowError, e:
        handle(e) # Realistically, this will be a different handler...
    else:
        do_something_with(result)

for i in range(10):
    wrap_process(i)

常に特定の例外をキャッチすることを忘れないでください。特定の例外がスローされることを予期していなかった場合は、処理ループを続行するのはおそらく安全ではありません。

次のコメントを編集します。

例外を本当に処理したくない場合は、それでも悪い考えだと思いますが、すべての例外(except:)をキャッチし、代わりに。handle(e)だけをキャッチしますpass。この時点で、実際の作業が行われる-blockwrap_process()をスキップして終了し、else:-loopの次の反復に進みますfor

エラーが黙って通過することは決してないことを覚えておいてください。

于 2011-05-20T11:19:36.820 に答える
8

例外の全体的な考え方は、それらが間接的な複数のレベルにわたって機能するということです。つまり、呼び出し階層の奥深くでエラー (またはその他の例外的な状態) が発生した場合でも、より高いレベルでそれをキャッチして適切に処理できます。

あなたの場合、呼び出し階層の下で関数試行2()および試行3()を呼び出す関数試行()があり、試行3()はメインループを終了させる例外的な状態に遭遇する可能性があるとします:

class JustContinueException(Exception):
    pass

for i in range(0,99):
    try:
        var = attempt() # calls attempt2() and attempt3() in turn
    except JustContinueException:
        continue # we don't need to log anything here
    except Exception, e:
        log(e)
        continue

    foo(bar)

def attempt3():
    try:
        # do something
    except Exception, e:
        # do something with e, if needed
        raise # reraise exception, so we catch it downstream

自分でダミーの例外をスローすることもできます。これにより、ループが終了するだけで、ログに記録されません。

def attempt3():
    raise JustContinueException()
于 2011-05-20T11:30:52.670 に答える
3

文脈は別として、質問に簡単に答えたいと思います。いいえ、関数はcontinueループ内で呼び出されることはできません。これは、このコンテキストに関する情報がないためです。また、それを処理するための周囲のループなしでその関数が呼び出されるとどうなるかなど、まったく新しいクラスの質問が発生しcontinueます。

しかし、関数は、現在実行している任意のループを呼び出し元に要求することをさまざまな手段で知らせることができます。continueもちろん、1 つの手段は戻り値です。たとえば、これを通知するためにFalseorを返します。Noneこれを通知する別の方法は、 special を発生させることExceptionです:

class ContinuePlease(Exception): pass

def f():
    raise ContinuePlease()

for i in range(10):
    try:
        f()
    except ContinuePlease:
        continue
于 2012-09-05T08:57:47.770 に答える
3

たぶん、あなたは継続をしたいですか?エリック・リッパートがそれらをどのように説明しているかを見てみましょう(気が狂う準備ができているなら、Python では次のように見えるかもしれません:

def attempt(operation, continuation):
    try:
        operation()
    except:
        log('operation failed!')
    continuation()

ループ内で次のことができます。

attempt(attempt_something, lambda: foo(bar)) # attempt_something is a function
于 2011-05-20T11:30:49.303 に答える
2

作業fooしたすべてのアイテムにマッピングしていると考えてください。attemptフィルターも同様で、これattemptをジェネレーターとして書くのは簡単です:

def attempted( items ):
    for item in items:
        try:
            yield attempt( item )
        except Exception, e:
            log(e)

print [foo(bar) for bar in attempted( items )]
于 2011-05-20T13:52:04.633 に答える
2

これを使用できます:

for l in loop:
  attempt() and foo(bar)

ただし、attempt() が True または False を返すことを確認する必要があります。

しかし、実際には、Johnsyweb の回答の方がおそらく優れています。

于 2011-05-20T11:30:22.583 に答える
1

通常、2 番目の回答は投稿しませんが、最初の回答が本当に気に入らない場合は、これが別の方法です。

関数は を返すことができることに注意してくださいtuple

#!/usr/bin/env python

def something_that_mail_fail(i):
    failed = False
    result = None
    try:
        result = 1.0 / (i % 4)
    except:
        failed = True # But we don't care
    return failed, result

for i in range(20):
    failed, result = something_that_mail_fail(i)
    if failed:
        continue
    for rah in ['rah'] * 3:
        print(rah)
    print(result)

私はそれtry ... except ... elseが進むべき道だと主張していますが、エラーを黙って無視するべきではありません。警告emptorとそのすべて。

于 2011-05-21T00:15:45.453 に答える
0

ブロックを除いて、try の外で for ループを試してください

この回答は Python 3.4 を念頭に置いていましたが、新しいバージョンにはより良い方法があります。これが私の提案です

システムをインポート
sys.version の「3.4」の場合:
    from termcolor import 色付き

def list_attributes (module_name): '''この関数を呼び出す前にモジュールをインポートしてください.s ''' インデックスの場合、enumerate(dir(module_name)) のメソッド: 試す: メソッド = str(メソッド) モジュール = '電子メール' 式 = モジュール + '.' + メソッド print('*' * len(式), '\n') print( str(index).upper() + '. ',colored( 式.upper(), 'red'), ' ', eval( 式 ). dir () , '...' , '\n' 2 ) print(' ' * len(式), '\n') print( eval( 式 + ' .doc ' ), '\n'*4, 'END OF DESCRIPTION FOR: ' + expression.upper(), '\n'*4) 例外 (AttributeError、NameError): 継続する そうしないと: 合格 最後に: 合格

于 2014-11-27T00:47:08.867 に答える
-4

編集:私が言ったすべての愚かさを削除しました...

最終的な答えは、そのようにコーディングする必要がないように、全体を書き直すことでした。

于 2011-05-21T13:59:14.497 に答える