読者です 読者をやめる 読者になる 読者になる

Pythonのfor-else

プログラミング

みんなのPython熟読中。ジェネレータの解説に出てきたコードでおもいっきりハマった。

#エラトステネスのふるい
def get_prime(x=2):
    while True:
        for i in range(2,x):
            if x % i == 0:
                break
        else:
            yield x
        x += 1

i = get_prime()
for c in range(5):
    print i.next()

↑をパッと見たときelseのインデント位置に違和感があったので↓の間違いだろうと思って
書き直して実行してみたらおかしなことになった。

def get_prime(x=2):
    while True:
        for i in range(2,x):
            if x % i == 0:
                break
            else:
                yield x
        x += 1

i = get_prime()
for c in range(5):
    print i.next()

実行結果

3
5
5
5
7

まあ, コードをよく見直してみたら明らかにおかしいのはわかったんだけど,
「はあ?じゃあ, このelseは何だ?」とか思ったわけですよ。
明らかにfor文にかかってますからねぇ。で, ドキュメントを見たところ,

ループ文は else 節を持つことができます; else 節は、 (for で) 反復処理対象のリストを使い切ってループが終了したとき、または (while で) 条件が偽になったときに実行されますが、 break 文でループが終了したときは実行されません。

と書いてあった。何故にforにelse?とか思うのだけど, まあ, ほかにいい予約語がないと
言われればそんな気がしないでもない。ちなみに, 正しい実行結果は↓。

2
3
5
7
11

人によっては↓の方がわかりやすいかも?

def get_prime(x=2):
    while True:
        if not [i for i in range(2, x) if x % i == 0]:
            yield x
        x += 1

しかし, Pythonってインデントといい, タプルといい, リスト内包表記といい,
Haskellにかなり似てるなあ。動的(Python)か静的(Haskell)かの違いはあるけど。