私はこの構文がどのように機能するのか理解しています:
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のコーダーがどのようにしてこの構文を頭の中で読んでいるのか疑問に思っています。おそらく、そのようなコードブロックをもっと簡単に解読できるようなものが足りないのでしょうか。
それはベテランの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ブロックを使用することは避けたいと思います。
一般的な構成は、何かが見つかるまでループを実行してからループから抜け出すことです。問題は、ループから抜け出した場合、またはループが終了した場合、どちらのケースが発生したのかを判断する必要があることです。 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番目の場合、バインディングはそれほど強くなく、メンテナンス中にエラーが発生する可能性があります。
Transforming Code to Beautiful、Idiomatic Python というタイトルのレイモンド・ヘッティンガーによる素晴らしいプレゼンテーションがあります。 for ... else
コンストラクト。関連するセクションは、「ループ内の複数の出口点の識別」です。 15:50から開始 で、約3分間続きます。高い点は次のとおりです。
for ... else
コンストラクトは、特定のGOTO
ユースケースの代替としてDonald Knuthによって考案されました。else
キーワードの再利用は、「Knuthが使用したものであり、当時、すべての[for
ステートメント]がif
とGOTO
を埋め込み、彼らはelse
;を期待していました」そのため、「このキーワードを変更しないのはなぜですか」という質問であれば、それから Cat Plus Plusがおそらく最も正確な答えを与えた –この時点では、既存のコードを破壊しすぎて実用的ではないだろう。しかし、あなたが本当に尋ねている質問がelse
がそもそも再利用された理由であるなら、それは明らかに、当時は良いアイデアのように思えた。
個人的には、else
が一目でループ内にあると誤解される可能性のある場所で# no break
をインラインでコメントする妥協が好きです。合理的かつ簡潔です。このオプションは、答えの最後に Bjornがリンクした要約 で簡単に言及しています。
完全を期すために、構文を少し変更するだけで、この構文が必要なプログラマーがすぐに使用できるようになります。
for item in sequence: process(item) else: # no break suite
*ビデオのその部分からのボーナス引用:「ちょうどlambdamakefunction、を呼び出したかのように、「ラムダは何をするのか?」
彼らはその言語に新しいキーワードを紹介したくなかったからです。それぞれが識別子を盗み、後方互換性の問題を引き起こすので、それは通常最後の手段です。
それを簡単にするために、あなたはそれをそのように考えることができます。
break
ループ内でfor
コマンドが検出された場合、else
部分は呼び出されません。break
ループ内でfor
コマンドが検出されない場合は、else
部分が呼び出されます。言い換えれば、forループの繰り返しがbreak
で "壊れていない"場合、else
部分が呼び出されます。
For/elseが何をしたのか、そしてもっと重要なのはいつ使うのかを知るための最も簡単な方法はbreak文がどこにジャンプするかに集中することでした。 For/else構文は単一ブロックです。 breakはブロックから飛び出して、else節を飛び越えます。 else節の内容が単にfor節の後に続いた場合、それは飛び越されることは決してないだろうから、それをifに入れることによって同等のロジックを提供しなければならないだろう。これは以前にも言われていましたが、これらの言葉では全くそうではなかったので、それは他の誰かを助けるかもしれません。次のコードを実行してみてください。明快さのために 'ノーブレーク'コメントに賛成です。
for a in range(3):
print(a)
if a==4: # change value to force break or not
break
else: #no break +10 for whoever thought of this decoration
print('for completed OK')
print('statement after for loop')
ドキュメンテーションにはelse、continueの素晴らしい説明があると思います
[...]リストが使い果たされてループが終了したとき(with)または条件がfalseになったとき(while)に実行されますが、ループがbreakステートメントで終了したときには実行されません。
私はそれを次のように読みました:
それでもループを実行する条件にある場合は、else何かを実行します。
技術的な部分はほとんど答えられているので、私のコメントはこれを生み出す混乱との関係にすぎませんrecycledキーワード。
Pythonは非常に雄弁なプログラミング言語であるため、キーワードの誤用はより悪名高いです。 else
キーワードは決定木の流れの一部を完全に記述したものです。私たち自身の言語では暗黙のです。
代わりに、このキーワードをwhile
およびfor
ステートメントと共に使用すると混乱が生じます。その理由は、プログラマーとしての私たちのキャリアから、else
ステートメントは決定木の中にあることを私たちに教えてくれました。その論理的範囲、条件付きでに続くパスを返すラッパー。一方、ループ文は何かを達成するための比喩的な明確な目標を持っています。目標はプロセスの継続的な反復の後に達成されます。
if / else
は、に続くパスを示します。は、「ゴール」が完了するまでパスをたどります。
問題は、else
が条件の最後のオプションを明確に定義するWordであるということです。 Wordのセマンティクスは、PythonとHuman Languageでは、両方ともsharedです。しかし、それ以外の人の言葉は、何かが完成した後に誰かまたは何かがとる行動を示すのに使われることは決してありません。完了の過程で問題が発生した場合に使用されます(break文のようなものです)。
最後に、キーワードはPythonに残ります。すべてのプログラマーがニーモニックデバイスのようにその使い方を理解するためのストーリーを考え出そうとするとき、それが間違いであることは明らかです。彼らが代わりにキーワードthen
を選んだなら、私は大好きでした。私はこのキーワードがその繰り返しの流れ、ループの後のpayoffに完全に適合すると信じています。
それはおもちゃを組み立てることにおけるあらゆるステップをたどった後に何人かの子供が持っているその状況に似ています:そしてそして何お父さん?
「iterable
が完全に使い果たされ、実行がfor
を終えた後に次のステートメントに進む直前に、else節が実行されるように」と読みました。したがって、反復がbreak
によって中断されると、これは実行されません。
私は同意します、それは「Elifが[条件が中断を起こす]ではない]のようなものです
私はこれが古いスレッドであることを知っています、しかし私は今同じ質問を検討しています、そして私がそれを理解する方法で誰かがこの質問への答えを捕らえたと確信していません。
私にとっては、For... else
またはWhile... else
ステートメント内のelse
を「読み取る」には3つの方法があります。これらはすべて等価です。
else
==
if the loop completes normally (without a break or error)
else
==
if the loop does not encounter a break
else
==
else not (condition raising break)
(おそらくそのような状態がある、あるいはあなたはループを持たないでしょう)したがって、本質的に、ループ内の「else」は実際には「Elif ...」です。ここで、「...」は(1)改行なし、つまり(2)NOTと同じです。 [休憩が発生している条件]
私は、else
は 'break'なしでは無意味なので、for...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
----------
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
はい、この比較は困難で面倒な場合があることを私は知っていますが、それは混乱を明確にしています。
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!
のドキュメントから:ステートメントを破って続行し、そうでなければループに関する節
ループ文はelse節を持つことができます。リストが使い果たされてループが終了したとき(with for)、または条件がfalseになったとき(with 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文のelse文よりも、try文の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
else
は他のもののように、あるいは他のもののように考えることができます。それはループでは行われませんでした。
これについて考える方法は、他の誰かが上で述べたことを見たことがないということです。
まず、forループは基本的にwhileループを囲む単なる構文上の糖であることを忘れないでください。例えば、ループ
for item in sequence:
do_something(item)
次のように書き換えることができます。
item = None
while sequence.hasnext():
item = sequence.next()
do_something(item)
次に、whileループは基本的に単にifブロックを繰り返すだけであることを忘れないでください。 whileループを「この条件が真であれば本文を実行してから戻ってきてもう一度確認する」と読むことができます。
そのため、while/elseは完全に理にかなっています。条件を1回だけチェックするのではなく、条件がfalseになるまでループするという機能が追加された、if/elseとまったく同じ構造です。
すべてのforループはwhileループの上にある単なる構文上の糖であるため、基礎となるwhileループの暗黙の条件が何であるかを理解する必要があります。条件はFalseになります。
これは検索以外の慣用句です。条件が真になるのを待っていたとしましょう。リモートサーバー上で開くためのポートとタイムアウトを設定します。そうすれば、while...else
構文を次のように利用できます。
import socket
import time
sock = socket.socket()
timeout = time.time() + 15
while time.time() < timeout:
if sock.connect_ex(('127.0.0.1', 80)) is 0:
print('Port is open now!')
break
print('Still waiting...')
else:
raise TimeoutError()
for i in range(3):
print(i)
if i == 2:
print("Too big - I'm giving up!")
break;
else:
print("Completed successfully")
ここでの「その他」は非常に単純です。
1、「for clause
が完了したら」
for i in range(3):
print(i)
if i == 2:
print("Too big - I'm giving up!")
break;
if "for clause is completed":
print("Completed successfully")
「for句は完成しました」というような長い文を書くことを望んでいるので、「else」を導入します。
ここでのelse
は本質的にifです。
2、しかしfor clause is not run at all
はどうですか
In [331]: for i in range(0):
...: print(i)
...:
...: if i == 9:
...: print("Too big - I'm giving up!")
...: break
...: else:
...: print("Completed successfully")
...:
Completed successfully
つまり、それは完全に論理的な組み合わせです。
if "for clause is completed" or "not run at all":
do else stuff
またはこのようにそれを置く:
if "for clause is not partially run":
do else stuff
またはこのように:
if "for clause not encounter a break":
do else stuff
素晴らしい答えは:
ここでの注意点は、while-elseがif-elseと区別がつかない構造がある(Pythonで)というDonald Knuthが以前に言ったこと(申し訳ありませんが、参照が見つかりません)から来ました。
x = 2
while x > 3:
print("foo")
break
else:
print("boo")
以下と同じフローを持ちます(低レベルの違いを除く)。
x = 2
if x > 3:
print("foo")
else:
print("boo")
要点は、if-elseはwhile-elseの構文上の糖と見なすことができ、break
ブロックの最後に暗黙のif
があることです。 while
はif
の前に教えることが多いので、if
ループはwhile
の拡張であるという逆の意味がより一般的です(これは単なる繰り返し/ループ条件付きチェックです)。ただし、while-else内のelse
ブロックは 毎回 conditionがfalseの場合に実行されます。
あなたの理解を容易にするためにそのように考えてください。
break
、return
などがないと、conditionが真でなくなった場合にのみループが終了し、そのような場合はelse
ブロックも1回実行されます。 Pythonのfor
の場合は、Cスタイルのfor
ループ(条件付き)を検討するか、それらをwhile
に変換する必要があります。
もう一つの注意:
ループ内の時期尚早の
break
、return
などは、conditionがtrueの間に実行がループから飛び出して再びチェックするために戻ってこないため、conditionがfalseになることを不可能にします。
Pythonはforループとwhileループの後にelseを使用しているため、ループに何も適用されない場合は何か他のことが起こります。例えば:
test = 3
while test == 4:
print("Hello")
else:
print("Hi")
出力は何度も何度も「こんにちは」になります(私が正しい場合)。
関数があるとしましょう
def broken(x) : return False if x==5 else True
これは5つだけが壊れていないことを意味します。今の場合壊れたは決して5で評価されません: -
for x in range(4):
if not broken(x) : break
else:
print("Everything broken... Doom is upon us")
出力を与えます: -
Everything broken... Doom is upon us
Wherebrokenが5で評価される場合: -
for x in range(6):
if not broken(x) : break
else:
print("Everything broken... Doom is upon us")
何も印刷されません。したがって、間接的に言って壊れていないものが少なくともあるということです。
しかし、あなたが不正行為をしたいと思った場合、あなたが見つけたものが壊れているのをスキップしてください。つまり、5が壊れていることがわかってもループを続行します。それ以外の場合は、ステートメントは表示されたままになります。あれは :-
for x in range(6):
if not broken(x) : continue
else:
print("Everything broken... Doom is upon us")
印刷します
Everything broken... Doom is upon us
私はそれが新しいものを作成する代わりに混乱を解消することを願っています:-)
私はただ自分自身でそれを理解しようとしていました。私は次のことが役立つことがわかりました!
•(else
ではなく)ループ内でif
とペアになっているfor
を考えてください。そうでない場合はループを中断します。 1つのelse
が複数のif
とペアになっている場合を除き、これを実行してください。
•if
sがまったく満足されない場合は、else
nameを実行します。
•複数のif
sは、実際にはif
-Elif
sと見なすこともできます。