ループを逆順で回す方法

Pythonのfor文はカウンタを意識する必要がないため大変便利ですが、逆順にする際は少々工夫が必要になります。

Contents

組み込み関数のreversedを使用する

組み込み関数にreversedというものがあります。この関数は、指定されたシーケンシャルオブジェクトを逆順にしたイテレータを返します。元のオブジェクトには何の影響もありません。

試してみましょう。

sample_list = [1, 2, 3, 4, 5]

for x in reversed(sample_list):
    print(x)
# 5
# 4
# 3
# 2
# 1

もちろん、rangeオブジェクトに対して使用することも可能です。4→0でループを回したい場合、以下のように記述することができます。

for x in reversed(range(0, 5)):
    print(x)

スライス構文を使用する

スライス構文はシーケンシャルオブジェクトのサブシーケンスを取得することができますが、:の3番目にステップを指定することができます。

例えば、1〜5が格納されたリストを2つ置きに要素を取得する場合、以下のように記述することができます。

sample_list = [1, 2, 3, 4, 5]
print(sample_list[0:5:2])
# [1, 3, 5]

このステップ数ですが、マイナスを指定することが可能で、マイナスを指定した場合は逆向きにステップを刻むことができるのです。

さきほどの逆ループのサンプルですが、スライス構文を使用すると以下のようにになります。

sample_list = [1, 2, 3, 4, 5]

for x in sample_list[::-1]:
    print(x)

rangeの場合は以下のように記述することができます。

for x in range(0, 5)[::-1]:
    print(x)

さて上の2つの方法、サンプルの通りrangeにも利用できるのですが、range自身にも第3引数でstepを指定することができるため、以下のように書いたほうがスマートかもしれません。

for x in range(4, -1, -1):
    print(x)

ただし、rangeは第2引数の直前までが対象となるため、範囲指定のミスに気をつけてください。

補足 reverseメソッド

リスト型にはreverseメソッドという機能があり、使用すると逆順のリストを得ることができます。この方法でもループの逆順を得ることはできるのですが、このメソッド、元のオブジェクトに対して破壊的に作用するためループを逆に回すためだけに用いるのは避けたほうが良いでしょう。

l = [1, 2, 3, 4, 5]
print(l.reverse())
# [5, 4, 3, 2, 1]
# ↑元のリストの順序が変わっている