Pythonのfor文によるループ処理(range, enumerate, zipなど)

Modified: | Tags: Python

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
source: for_usage.py

なお、Pythonでは括弧ではなくインデント(通常はスペース4個)でブロックを表現する。

forループを途中で終了: break

forループを途中で終了するにはbreakを使う。breakに到達した時点でループが終了する。

for name in l:
    if name == 'Bob':
        print('!!BREAK!!')
        break
    print(name)
# Alice
# !!BREAK!!
source: for_usage.py

条件分岐にはif文を使う。

特定の要素の処理をスキップ: continue

特定の要素に対する処理をスキップするにはcontinueを使う。

breakはforループ全体が終了するが、continueの場合はその要素に対するcontinue文以降の処理がスキップされるのみ。forループは継続し、次の要素の処理が実行される。

for name in l:
    if name == 'Bob':
        print('!!SKIP!!')
        continue
    print(name)
# Alice
# !!SKIP!!
# Charlie
source: for_usage.py

forループ正常終了後の処理: else

forループが終わりまで正常に実行された後に何らかの処理を行いたい場合はelseを使う。

for name in l:
    print(name)
else:
    print('!!FINISH!!')
# Alice
# Bob
# Charlie
# !!FINISH!!
source: for_usage.py

breakによって途中で終了した場合はelseの処理は実行されない。

for name in l:
    if name == 'Bob':
        print('!!BREAK!!')
        break
    print(name)
else:
    print('!!FINISH!!')
# Alice
# !!BREAK!!
source: for_usage.py

continueの場合はforループが最後まで到達するのでelseの処理が実行される。

for name in l:
    if name == 'Bob':
        print('!!SKIP!!')
        continue
    print(name)
else:
    print('!!FINISH!!')
# Alice
# !!SKIP!!
# Charlie
# !!FINISH!!
source: for_usage.py

elsecontinueを組み合わせると多重ループの内側のループから一気に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
source: for_usage.py

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
source: for_usage.py

スライスについての詳細は以下の記事を参照。

インデックス(カウンタ): range()

Pythonのfor文でインデックス(カウンタ)を取得するにはrange()を使う。

for i in range(3):
    print(i)
# 0
# 1
# 2
source: for_range.py

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]
source: for_range.py

for文で使うと以下のようになる。

for i in range(10, 0, -3):
    print(i)
# 10
# 7
# 4
# 1
source: for_range.py

降順や浮動小数点数floatの場合など、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]

リスト内包表記を使うと、要素を処理するだけでなく、条件に応じて要素を抽出したりすることも可能なので覚えておいて損はない。

詳細は以下の記事を参照。

関連カテゴリー

関連記事