web-dev-qa-db-ja.com

Python=のイテレータで例外が発生するのはなぜですか?

Java(C#でもやや似た構文))の反復子の構文は次のとおりです。

Iterator it = sequence.iterator();

while (it.hasNext()) {
    System.out.println(it.next());
}

それは理にかなっています。 Pythonでの同等の構文は次のとおりです。

it = iter(sequence)
while True:
    try:
        value = it.next() 
    except StopIteration:
        break
    print(value)

例外は例外的な状況でのみ使用されることになっていると思いました。

Python例外を使用して反復を停止するのはなぜですか?

48

StopIterationのtry-exceptブロックを明示的に記述せずにその式を記述する非常にPython的な方法があります。

# some_iterable is some collection that can be iterated over
# e.g., a list, sequence, dict, set, itertools.combination(...)

for value in some_iterable:
    print(value)

StopIterationが導入された理由とイテレータの背後にあるロジックについて詳しく知りたい場合は、関連するPEP 234255 を参照してください。

pythonの一般的な原則は、何かを行う1つの方法を持つことです(import this)、そしてできればその美しく、明示的で、読みやすく、シンプルで、Pythonicメソッドが満足するものです。 pythonはイテレータにhasNextメンバー関数を与えないため、同等のコードが必要なだけです;イテレータを直接ループすることを人々に好む(そしてあなたが何か他のことをする必要がある場合)それを読んでみて、例外をキャッチしてください)。

イテレータの終わりでのStopIteration例外の自動キャッチは理にかなっており、ファイルの終わりを超えて読み取った場合に発生するEOFErrorの類似物です。

50
dr jimbob

pythonが例外を使用して反復を停止する理由は PEP 234 に記載されています:

反復の終了を通知する例外がそれほど高価ではないかどうかは疑問視されてきました。 StopIteration例外のいくつかの代替案が提案されています:終了を通知する特別な値End、イテレータが終了したかどうかをテストする関数end()、さらにIndexError例外を再利用します。

  • 特殊な値には、シーケンスにその特殊な値が含まれている場合、そのシーケンスに対するループが警告なしに途中で終了するという問題があります。 nullで終了するC文字列を使用した経験から、これが引き起こす可能性のある問題がわからない場合は、Pythonイントロスペクションツールがすべての組み込み名のリストを繰り返し処理すると仮定すると、特別なEnd値は組み込みの名前でした!

  • End()関数を呼び出すには、反復ごとに2回の呼び出しが必要です。 2つの呼び出しは、1つの呼び出しと例外のテストに比べてはるかに高価です。特に、タイムクリティカルなforループは、例外について非常に安価にテストできます。

  • IndexErrorを再利用すると、それが本物のエラーになる可能性があるため、混乱が生じる可能性があります。

注:シーケンスをループする慣用的なpython方法は次のとおりです。

for value in sequence:
    print (value)
28
lesmana

それは哲学の違いです。 Pythonicの設計哲学は [〜#〜] eafp [〜#〜] です:

許可より許しを求める方が簡単です。この一般的なPythonコーディングスタイルは、有効なキーまたは属性の存在を想定し、想定が偽であることが判明した場合に例外をキャッチします。このクリーンで高速なスタイルは、多数のtryexceptステートメント。この手法は [〜#〜] lbyl [〜#〜] スタイルと対照的ですCなどの他の多くの言語に共通...

20

Java実装にhasNext()メソッドがあるため、next()を実行する前に空のイテレータを確認できます。 next() on a Java要素が残っていないイテレータ、a NoSuchElementExceptionがスローされます

つまり、効果的に、Pythonのtry..exceptのようにJavaでtry..catchを実行できます。そして、はい、以前の回答のように、哲学はveryPythonicの世界で重要です。

7
yati sagade