Pythonのfor文によるループ処理(range, enumerate, zipなど)
Pythonのfor文によるループ処理(繰り返し処理)について説明する。基本的な文法と、for文とrange()
やenumerate()
, zip()
などを組み合わせて使う例を紹介する。
条件式がTrue
である限り処理を繰り返すwhile文によるループ処理もある。
Pythonのfor文の基本的な書き方: for ... in ... :
Pythonのfor文は他言語のforeach文と同等
C系のプログラミング言語のfor文(forループ)はカウンタ変数(インデックス)と継続条件を使って記述する。
for (int i = 0; i < 10; i++) {
処理
}
Pythonのfor文はカウンタ変数を使わずに記述する。以下の変数名
は任意の名称。
for 変数名 in イテラブルオブジェクト:
処理
他言語におけるforeach文に相当し、リストなどのイテラブルオブジェクトの要素が順番に変数に代入され、繰り返し処理が行われる。
Pythonにおけるfor文は、Cのようにカウンタ変数の増減や評価を直接記述することはできず、他の言語におけるforeach文と同等である。 Foreach文 - Wikipedia
具体例は以下の通り。
l = ['Alice', 'Bob', 'Charlie']
for name in l:
print(name)
# Alice
# Bob
# Charlie
なお、Pythonでは括弧ではなくインデント(通常はスペース4個)でブロックを表現する。
forループを途中で終了: break
forループを途中で終了するにはbreak
を使う。break
に到達した時点でループが終了する。
for name in l:
if name == 'Bob':
print('!!BREAK!!')
break
print(name)
# Alice
# !!BREAK!!
条件分岐にはif文を使う。
特定の要素の処理をスキップ: continue
特定の要素に対する処理をスキップするにはcontinue
を使う。
break
はforループ全体が終了するが、continue
の場合はその要素に対するcontinue
文以降の処理がスキップされるのみ。forループは継続し、次の要素の処理が実行される。
for name in l:
if name == 'Bob':
print('!!SKIP!!')
continue
print(name)
# Alice
# !!SKIP!!
# Charlie
forループ正常終了後の処理: else
forループが終わりまで正常に実行された後に何らかの処理を行いたい場合はelse
を使う。
for name in l:
print(name)
else:
print('!!FINISH!!')
# Alice
# Bob
# Charlie
# !!FINISH!!
break
によって途中で終了した場合はelse
の処理は実行されない。
for name in l:
if name == 'Bob':
print('!!BREAK!!')
break
print(name)
else:
print('!!FINISH!!')
# Alice
# !!BREAK!!
continue
の場合はforループが最後まで到達するのでelse
の処理が実行される。
for name in l:
if name == 'Bob':
print('!!SKIP!!')
continue
print(name)
else:
print('!!FINISH!!')
# Alice
# !!SKIP!!
# Charlie
# !!FINISH!!
else
とcontinue
を組み合わせると多重ループの内側のループから一気にbreak
で抜け出すことができる。以下の記事を参照。
範囲を指定して一部の要素のみを取り出し: スライス
リストの範囲を指定して一部の要素のみを取り出すには、スライス[start:stop]
を使う。start
, stop
には0
始まりのインデックスを指定する。stop
番目の要素は含まれないので注意。
l = ['A', 'B', 'C', 'D', 'E', 'F', 'G']
for c in l[2:5]:
print(c)
# C
# D
# E
start
, stop
を省略したり、[start:stop:step]
としてstep
ごとの要素を取り出したりもできる。奇数番目のみ、偶数番目のみの要素を取り出す例は以下の通り。
for c in l[::2]:
print(c)
# A
# C
# E
# G
for c in l[1::2]:
print(c)
# B
# D
# F
スライスについての詳細は以下の記事を参照。
インデックス(カウンタ): range()
Pythonのfor文でインデックス(カウンタ)を取得するにはrange()
を使う。
for i in range(3):
print(i)
# 0
# 1
# 2
range()
は引数の数によって指定できる内容と返される結果が異なる。
range(stop)
:0 ≦ i < stop
の連番range(start, stop)
:start ≦ i < stop
の連番range(start, stop, step)
:start ≦ i < stop
の範囲でstep
ごとの整数値step
に負の値を指定すると逆順になる
以下、説明のためlist()
でリストに変換して出力するが、上の例のようにfor文で使う際にはリストに変換する必要はない。
print(list(range(6)))
# [0, 1, 2, 3, 4, 5]
print(list(range(10, 13)))
# [10, 11, 12]
print(list(range(0, 10, 3)))
# [0, 3, 6, 9]
print(list(range(10, 0, -3)))
# [10, 7, 4, 1]
for文で使うと以下のようになる。
for i in range(10, 0, -3):
print(i)
# 10
# 7
# 4
# 1
降順や浮動小数点数float
の場合など、range()
についての詳細は以下の記事を参照。
- 関連記事: Pythonのrange関数の使い方
リストの要素とインデックス: enumerate()
リストなどのイテラブルオブジェクトの要素とインデックス(カウンタ)を同時に取得するにはenumerate()
を使う。
l = ['Alice', 'Bob', 'Charlie']
for name in l:
print(name)
# Alice
# Bob
# Charlie
for i, name in enumerate(l):
print(i, name)
# 0 Alice
# 1 Bob
# 2 Charlie
enumerate()
の第二引数には開始値を指定できる。0始まりではなく任意の整数値から始められる。
for i, name in enumerate(l, 42):
print(i, name)
# 42 Alice
# 43 Bob
# 44 Charlie
enumerate()
に増分step
を指定する引数はないが、以下のようにすると実現可能。
step = 3
for i, name in enumerate(l):
print(i * step, name)
# 0 Alice
# 3 Bob
# 6 Charlie
複数リストの要素(複数変数): zip()
複数のイテラブルオブジェクト(リストなど)の要素を複数の変数として取得するにはzip()
を使う。
names = ['Alice', 'Bob', 'Charlie']
ages = [24, 50, 18]
for name, age in zip(names, ages):
print(name, age)
# Alice 24
# Bob 50
# Charlie 18
2変数に限らず、3つ以上のイテラブルオブジェクトをまとめることも可能。
points = [100, 85, 90]
for name, age, point in zip(names, ages, points):
print(name, age, point)
# Alice 24 100
# Bob 50 85
# Charlie 18 90
要素数が異なる場合の動作など、詳細は以下の記事を参照。
例のように、zip()
では複数のイテラブルオブジェクトの要素を同時に順番に取得できる。複数のイテラブルオブジェクトの要素のすべての組み合わせを取得したい場合は後述のitertools.product()
を使う。
複数リストの要素とインデックス: enumerate(), zip()
複数のイテラブルオブジェクト(リストなど)の要素とインデックス(カウンタ)を同時に取得するにはenumerate()
とzip()
を組み合わせて使う。
zip()
の分の変数名を括弧()
で囲む必要があるので注意。
names = ['Alice', 'Bob', 'Charlie']
ages = [24, 50, 18]
for i, (name, age) in enumerate(zip(names, ages)):
print(i, name, age)
# 0 Alice 24
# 1 Bob 50
# 2 Charlie 18
逆順(後ろから取得): reversed()
イテラブルオブジェクト(リストなど)の要素を逆順で後ろから取得するには、reversed()
を使う。
l = ['Alice', 'Bob', 'Charlie']
for name in reversed(l):
print(name)
# Charlie
# Bob
# Alice
range
オブジェクトも逆転可能。step
に負の値を指定して逆転させることもできる。
for i in reversed(range(3)):
print(i)
# 2
# 1
# 0
for i in range(2, -1, -1):
print(i)
# 2
# 1
# 0
enumerate
オブジェクトは逆転できない。list()
でリスト化すればOK。インデックス(カウンタ)は逆転したくない場合はenumerate()
の中でreversed()
を使う。
# for i, name in reversed(enumerate(l)):
# print(i, name)
# TypeError: 'enumerate' object is not reversible
for i, name in reversed(list(enumerate(l))):
print(i, name)
# 2 Charlie
# 1 Bob
# 0 Alice
for i, name in enumerate(reversed(l)):
print(i, name)
# 0 Charlie
# 1 Bob
# 2 Alice
zip
オブジェクトも逆転できない。これもlist()
でリスト化すればOK。
l2 = [24, 50, 18]
# for name, age in reversed(zip(l, l2)):
# print(name, age)
# TypeError: 'zip' object is not reversible
for name, age in reversed(list(zip(l, l2))):
print(name, age)
# Charlie 18
# Bob 50
# Alice 24
多重ループ: itertools.product()
Pythonにおける多重ループは以下のように書ける。Pythonではインデントでブロックを表すので、さらにインデントを加えるだけ。
l1 = [1, 2, 3]
l2 = [10, 20, 30]
for i in l1:
for j in l2:
print(i, j)
# 1 10
# 1 20
# 1 30
# 2 10
# 2 20
# 2 30
# 3 10
# 3 20
# 3 30
標準ライブラリitertools
モジュールのitertools.product()
を使うとforをネストすることなく多重ループと同様の結果が得られる。
import itertools
l1 = [1, 2, 3]
l2 = [10, 20, 30]
for i, j in itertools.product(l1, l2):
print(i, j)
# 1 10
# 1 20
# 1 30
# 2 10
# 2 20
# 2 30
# 3 10
# 3 20
# 3 30
2つ以上のイテラブルオブジェクトを引数に指定することも可能。詳細は以下の記事を参照。
多重ループの内側のループから一気にbreak
で抜け出す場合はitertools.product()
を使うと簡単。以下の記事を参照。
辞書(dict)のforループ
辞書dict
のオブジェクトをforループで回すと、辞書のキーが取得できる。
d = {'key1': 1, 'key2': 2, 'key3': 3}
for k in d:
print(k)
# key1
# key2
# key3
値あるいはキーと値のペアを取得したい場合は、values()
メソッド、items()
メソッドを使う。
for v in d.values():
print(v)
# 1
# 2
# 3
for k, v in d.items():
print(k, v)
# key1 1
# key2 2
# key3 3
詳細は以下の記事を参照。
リスト内包表記
リストなどのイテラブルオブジェクトの要素を処理して新たなリストを生成する場合は、for文よりもリスト内包表記を使うとシンプルに記述できる。
リスト内包表記は以下のように書く。
[式 for 変数名 in イテラブルオブジェクト]
等価なfor文とともに例を示す。
squares = [i**2 for i in range(5)]
print(squares)
# [0, 1, 4, 9, 16]
squares = []
for i in range(5):
squares.append(i**2)
print(squares)
# [0, 1, 4, 9, 16]
リスト内包表記を使うと、要素を処理するだけでなく、条件に応じて要素を抽出したりすることも可能なので覚えておいて損はない。
詳細は以下の記事を参照。
- 関連記事: Pythonリスト内包表記の使い方