Pythonのforループのelse節を冗長に読解

Python Tutorialの4.4のソースで「これ正しいんだっけ?」と悩み始めたら不必要に難しく考えてしまってはまりそうになったので、不必要に冗長に読解してみます。


元のネタはこれ

for x in range(2, 10):
    for x in range(2, x):
        if n % x == 0:
            print n, 'eqluals', x, '*', n/x
            break
    else:
        print n, 'is a prime number'


これを最初に見た時に次のように勘違いしてしまいました。

for x in range(2, 10):
    for x in range(2, x):
        if n % x == 0:
            print n, 'equals', x, '*', n/x
            break
        else:
            print n, 'is a prime number'


が、元ネタに

(Yes, this is the correct code. Look closely: the else clause belongs to the for loop, not the if statement.)

とあるように、上のソースじゃないと正しく(意図されたとおりには)機能してくれません。


では、ここから無意味な読解をします。

if節の中のprintの時のnとxの値とターミナル上の表示を青、
else節の中のprintの時のnとxの値とターミナル上の表示を赤、
実際には実行されない状態のnとxの値を緑で表します。

n = 2, x = null => 2 is a prime number
n = 3, x = 2
n = 3, x = null => 3 is a prime number
n = 4, x = 2 => 4 equals 2 * 2 # after print this, for x in range(2,n) break
# n = 4, x = 3
# n = 4, x = null

n = 5, x = 2
n = 5, x = 3
n = 5, x = 4
n = 5, x = null => 5 is a prime number
n = 6, x = 2 => 6 equals 2 * 3 # after print this, for x in range(2, n) break
# n = 6, x = 3
# n = 6, x = 4
# n = 6, x = 5

# n = 6, x = null
n = 7, x = 2
n = 7, x = 3
n = 7, x = 4
n = 7, x = 5
n = 7, x = 6
n = 7, x = null => 7 is a prime number
n = 8, x = 2 => 8 equals 2 * 4 # after print this, for x in range(2, n) break
# n = 8, x = 3
# n = 8, x = 4
# n = 8, x = 5
# n = 8, x = 6
# n = 8, x = 7
# n = 8, x = null

n = 9, x = 2
n = 9, x = 3 => 9 equals 3 * 3 # after print this, for x in range(2, n) break
# n = 9, x = 4
# n = 9, x = 5
# n = 9, x = 6
# n = 9, x = 7
# n = 9, x = 8
# n = 9, x = null


forループのelse節はループさせるものがなくなった状態になった時に実行されるので、例えば、range(2,2)は[](空のリスト)を返すので、if文を評価するネストに行かずelse節の中を実行しています。


次にrange(2, 4)は[2, 3]を返し、else節に行く前にif文の評価を行います。n = 2, x = 2の時、ifはTrueを返すので、breakが発生し、range(2, 4)の2度目(3の値)のケースは評価されず、forループでnullを掴んでいるわけでもないので、else節を実行するわけでもなく、次のrange(2, 5)のforループの評価が始まります。


と言葉にすると不必要に冗長になりますが、ループの中で論理的にどう動いているのかこんがらがってきたら面倒臭がらずに1つずつ値を書いてみて、どう評価されてどう分岐するのかゆっくり考えると全然難しい問題ではない、ということが分かるいい実例でした。。。