630

この構成がどのように機能するかを理解しています。

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

    if i == 9:
        print("Too big - I'm giving up!")
        break
else:
    print("Completed successfully")

elseしかし、なぜここでキーワードとして使用されているのかわかりません。問題のコードは、forブロックが完了していない場合にのみ実行されることを示唆しているためです。これは、ブロックが完了するのとは逆です。私がそれについてどのように考えても、私の脳はforステートメントからelseブロックへとシームレスに進むことができません。私にとって、continueまたはcontinuewithもっと理にかなっているでしょう(そして私はそれをそのように読むように自分自身を訓練しようとしています)。

Pythonコーダーがこの構造を頭の中で(または、必要に応じて声に出して)どのように読み取るのか疑問に思っています。おそらく、そのようなコードブロックをより簡単に解読できるようにする何かが欠けていますか?

4

23 に答える 23

786

一般的な構造は、何かが見つかるまでループを実行し、その後ループから抜け出すことです。問題は、ループから抜け出すか、ループが終了した場合、どちらのケースが発生したかを判断する必要があることです。1 つの方法は、ループがどのように終了したかを確認するために 2 番目のテストを実行できるフラグまたはストア変数を作成することです。

たとえば、リストを検索し、フラグ項目が見つかるまで各項目を処理してから処理を停止する必要があるとします。フラグ項目がない場合は、例外を発生させる必要があります。

Python for...elseコンストラクトを使用する

for i in mylist:
    if i == theflag:
        break
    process(i)
else:
    raise ValueError("List argument missing terminal flag.")

これを、このシンタックス シュガーを使用しないメソッドと比較してください。

flagfound = False
for i in mylist:
    if i == theflag:
        flagfound = True
        break
    process(i)

if not flagfound:
    raise ValueError("List argument missing terminal flag.")

最初のケースでraiseは、それが動作する for ループにしっかりとバインドされています。2 番目のバインディングはそれほど強力ではなく、メンテナンス中にエラーが発生する可能性があります。

于 2012-04-02T17:13:15.520 に答える
369

ベテランの Python コーダーにとっても、これは奇妙な構造です。forループと組み合わせて使用​​すると、基本的には「イテラブル内のいくつかのアイテムを見つけ、何も見つからない場合は...」を意味します。次のように:

found_obj = None
for obj in objects:
    if obj.key == search_key:
        found_obj = obj
        break
else:
    print('No object found.')

しかし、この構文が表示される場合はいつでも、検索を関数にカプセル化することをお勧めします。

def find_obj(search_key):
    for obj in objects:
        if obj.key == search_key:
            return obj

または、リスト内包表記を使用します。

matching_objs = [o for o in objects if o.key == search_key]
if matching_objs:
    print('Found {}'.format(matching_objs[0]))
else:
    print('No object found.')

他の 2 つのバージョンと意味的に同等ではありませんが、リスト全体を反復するかどうかが問題にならない、パフォーマンスが重要でないコードでは十分に機能します。同意しない人もいるかもしれませんが、私は個人的には、プロダクション コードで for-else または while-else ブロックを使用することは絶対に避けたいと思っています。

[Python-ideas] for...else スレッドのまとめも参照してください。

于 2012-04-02T16:30:48.063 に答える
38

彼らは言語に新しいキーワードを導入したくなかったからです。それぞれが識別子を盗み、下位互換性の問題を引き起こすため、通常は最後の手段です。

于 2012-04-02T16:20:03.813 に答える
23

ドキュメントにはelseの素晴らしい説明があると思い ます、続けてください

[...] リストが使い果たされてループが終了したとき (for を使用)、または条件が false になったとき (while を使用) に実行されますが、break ステートメントによってループが終了したときは実行されません。

出典: Python 2 ドキュメント: 制御フローのチュートリアル

于 2014-05-13T08:28:54.667 に答える
14

私はそれを次のように読みました:

まだループを実行する条件にある場合は、何かを実行します。それ以外の場合は、他のことを実行します。

于 2012-04-02T16:20:33.567 に答える
7

iterable「が完全に使い果たされ、 が終了して次のステートメントに実行が移ろうとしているforときに、else 句が実行される」と読みました。したがって、繰り返しが によって中断されるbreakと、これは実行されません。

于 2014-07-07T04:32:57.717 に答える
6

私は同意します、それは「elif not [condition(s) raise break]」のようなものです。

これが古いスレッドであることは知っていますが、現在同じ質問を調べています。この質問に対する回答を私が理解している方法で誰かが理解しているかどうかはわかりません。

else私にとって、 in For... elseorステートメントを「読む」方法は 3 つありますがWhile... else、これらはすべて同等です。

  1. else == if the loop completes normally (without a break or error)
  2. else == if the loop does not encounter a break
  3. else == else not (condition raising break)(おそらくそのような条件があるか、ループがないでしょう)

したがって、基本的に、ループ内の「else」は実際には「elif ...」であり、「...」は (1) ブレークなし、(2) NOT [ブレークを発生させる条件] と同等です。

else重要なのは、「休憩」がなければ意味がないということだと思うので、 afor...elseには以下が含まれます。

for:
    do stuff
    conditional break # implied by else
else not break:
    do more stuff

したがって、for...elseループの重要な要素は次のとおりであり、より平易な英語で次のように読むことができます。

for:
    do stuff
    condition:
        break
else: # read as "else not break" or "else not condition"
    do more stuff

他のポスターが言っているように、通常、ループが探しているものを見つけることができるとブレークが発生するため、else:「ターゲットアイテムが見つからない場合の対処方法」になります。

例外処理、ブレーク、および for ループをまとめて使用することもできます。

for x in range(0,3):
    print("x: {}".format(x))
    if x == 2:
        try:
            raise AssertionError("ASSERTION ERROR: x is {}".format(x))
        except:
            print(AssertionError("ASSERTION ERROR: x is {}".format(x)))
            break
else:
    print("X loop complete without error")

結果

x: 0
x: 1
x: 2
ASSERTION ERROR: x is 2
----------
# loop not completed (hit break), so else didn't run

ブレークが打たれた簡単な例。

for y in range(0,3):
    print("y: {}".format(y))
    if y == 2: # will be executed
        print("BREAK: y is {}\n----------".format(y))
        break
else: # not executed because break is hit
    print("y_loop completed without break----------\n")

結果

y: 0
y: 1
y: 2
BREAK: y is 2
----------
# loop not completed (hit break), so else didn't run

ブレークがなく、ブレークが発生する条件がなく、エラーが発生していない単純な例。

for z in range(0,3):
     print("z: {}".format(z))
     if z == 4: # will not be executed
         print("BREAK: z is {}\n".format(y))
         break
     if z == 4: # will not be executed
         raise AssertionError("ASSERTION ERROR: x is {}".format(x))
else:
     print("z_loop complete without break or error\n----------\n")

結果

z: 0
z: 1
z: 2
z_loop complete without break or error
----------
于 2016-01-06T17:40:15.687 に答える
6

ここelseでのキーワードは混乱を招く可能性があり、多くの人が指摘しているようnobreakに、のようなものnotbreakがより適切です。

for ... else ...論理的に理解するためにtry...except...else、 ではなくと比較してくださいif...else...。ほとんどの Python プログラマーは、次のコードに精通しています。

try:
    do_something()
except:
    print("Error happened.") # The try block threw an exception
else:
    print("Everything is find.") # The try block does things just find.

break同様に、特別な種類のと考えてExceptionください:

for x in iterable:
    do_something(x)
except break:
    pass # Implied by Python's loop semantics
else:
    print('no break encountered')  # No break statement was encountered

違いはpython暗示的except breakであり、書き出すことはできないため、次のようになります。

for x in iterable:
    do_something(x)
else:
    print('no break encountered')  # No break statement was encountered

はい、この比較が困難で面倒なことは承知していますが、混乱を明確にしています。

于 2017-04-27T03:36:06.960 に答える
5

elseステートメント ブロック内のコードは、forループが壊れていない場合に実行されます。

for x in xrange(1,5):
    if x == 5:
        print 'find 5'
        break
else:
    print 'can not find 5!'
#can not find 5!

ドキュメントから: break と continue ステートメント、および else ループの句

ループ ステートメントには、else 句を含めることができます。ループがリストの枯渇によって終了したとき (for を使用)、または条件が false になったとき (while を使用) に実行されますが、break ステートメントによってループが終了したときは実行されません。これは、素数を検索する次のループによって例示されます。

>>> for n in range(2, 10):
...     for x in range(2, n):
...         if n % x == 0:
...             print(n, 'equals', x, '*', n//x)
...             break
...     else:
...         # loop fell through without finding a factor
...         print(n, 'is a prime number')
...
2 is a prime number
3 is a prime number
4 equals 2 * 2
5 is a prime number
6 equals 2 * 3
7 is a prime number
8 equals 2 * 4
9 equals 3 * 3

(はい、これは正しいコードです。よく見てください。else 句は、if ステートメントではなく、for ループに属しています。)

ループで使用する場合、else 句は、if ステートメントよりも try ステートメントの else 句と共通点があります。try ステートメントの else 句は、例外が発生しないときに実行され、ループの else 句は、ブレークが発生しないときに実行されます。 . try ステートメントと例外の詳細については、例外の処理を参照してください。

これも C から借用した continue ステートメントは、ループの次の繰り返しに進みます。

>>> for num in range(2, 10):
...     if num % 2 == 0:
...         print("Found an even number", num)
...         continue
...     print("Found a number", num)
Found an even number 2
Found a number 3
Found an even number 4
Found a number 5
Found an even number 6
Found a number 7
Found an even number 8
Found a number 9
于 2016-08-26T04:42:30.600 に答える
5

上記の他の誰も言及していないことを考える方法は次のとおりです。

まず、for ループは基本的に while ループの構文糖衣に過ぎないことを思い出してください。たとえば、ループ

for item in sequence:
    do_something(item)

(おおよそ) のように書き換えることができます。

item = None
while sequence.hasnext():
    item = sequence.next()
    do_something(item)

次に、while ループは基本的に if ブロックを繰り返すだけであることを思い出してください。while ループはいつでも「この条件が true の場合は本体を実行し、戻ってもう一度確認する」と読むことができます。

そのため、while/else は完全に理にかなっています。これは if/else とまったく同じ構造であり、条件を 1 回チェックするだけでなく、条件が false になるまでループする機能が追加されています。

そして、for/else も完全に理にかなっています。すべての for ループは while ループの上にある構文糖衣にすぎないため、根底にある while ループの暗黙の条件が何であるかを理解するだけでよく、else はそのときに対応します。 condition が False になります。

于 2018-12-11T17:52:30.190 に答える
1

elseループで行われなかった残りの部分、またはその他の部分のように考えることができます 。

于 2012-04-02T16:25:26.833 に答える
0

ループが正常に終了した後、else 句が実行されます。つまり、for/while の直後の :==> else ブロックは、ループが break ステートメントで終了していない場合にのみ実行されます。

for item in lista:
if(obj == item ):
    print("if True then break will run and else not run")
    break;
else:
print("in  else => obj not fount ")
于 2021-09-05T17:24:42.123 に答える