はじめに
pythonのfor文には複数の書き方があり、使い分けや用途など迷う場面が出てきます。
そこで、頭の整理も兼ねてまとめてみました。基本的な構文から内包表記、非同期処理までを範囲にしています。
これからPythonを始める方や、自分と同じように「for文の使い分けがよくわからない」という方のお力になれたら嬉しいです。
1. 基本的なfor文
まずは基本から。
リストのループ
リストの要素を1つずつ取り出して処理するパターンです。
fruits = ["りんご", "みかん", "ぶどう"]
for fruit in fruits:
print(fruit)
# 実行結果:
# りんご
# みかん
# ぶどう
変数名は何でも良いですが、「複数形のリスト → 単数形の変数」にすると読みやすくなります。fruits → fruit、users → userのような命名がおすすめです。
辞書のループ
辞書(dict)をループする方法は3パターンあります。
student = {"name": "田中", "age": 20, "grade": "A"}
for key in student:
print(key)
# 実行結果:
# name
# age
# grade
student = {"name": "田中", "age": 20, "grade": "A"}
for value in student.values():
print(value)
# 実行結果:
# 田中
# 20
# A
student = {"name": "田中", "age": 20, "grade": "A"}
for key, value in student.items():
print(f"{key}: {value}")
# 実行結果:
# name: 田中
# age: 20
# grade: A
2. enumerate() - インデックス付きループ
「何番目の要素か」を知りたい時に使います。
fruits = ["りんご", "みかん", "ぶどう"]
for i, fruit in enumerate(fruits):
print(f"{i}: {fruit}")
# 実行結果:
# 0: りんご
# 1: みかん
# 2: ぶどう
開始番号を指定する
start引数で開始番号を変更できます。
fruits = ["りんご", "みかん", "ぶどう"]
for i, fruit in enumerate(fruits, start=2):
print(f"{i}番目: {fruit}")
# 実行結果:
# 2番目: りんご
# 3番目: みかん
# 4番目: ぶどう
進捗表示での活用例
大量のデータを処理する時、進捗を表示したい場面で利用できます。
tasks = ["データ取得", "変換処理", "保存処理", "検証"]
total = len(tasks)
for i, task in enumerate(tasks, start=1):
print(f"[{i}/{total}] {task}を実行中...")
# 実行結果:
# [1/4] データ取得を実行中...
# [2/4] 変換処理を実行中...
# [3/4] 保存処理を実行中...
# [4/4] 検証を実行中...
3. range() - 回数指定ループ
「N回繰り返したい」時に使います。他の言語でいうfor (int i = 0; i < N; i++)に相当します。
基本的な使い方
for i in range(5):
print(i)
# 実行結果:
# 0
# 1
# 2
# 3
# 4
for i in range(1, 6):
print(i)
# 実行結果:
# 1
# 2
# 3
# 4
# 5
for i in range(0, 11, 2):
print(i)
# 実行結果:
# 0
# 2
# 4
# 6
# 8
# 10
カウントダウンも可能
第3引数に負の値を指定すると、逆順にループできます。
for i in range(5, 0, -1):
print(i)
print("発射!")
# 実行結果:
# 5
# 4
# 3
# 2
# 1
# 発射!
4. zip() - 複数リストの同時ループ
複数のリストを同時にループしたい時に使います。対応する要素をペアで取り出せます。
names = ["田中", "佐藤", "鈴木"]
scores = [85, 92, 78]
for name, score in zip(names, scores):
print(f"{name}さん: {score}点")
# 実行結果:
# 田中さん: 85点
# 佐藤さん: 92点
# 鈴木さん: 78点
3つ以上のリストも同時に処理可能
names = ["田中", "佐藤", "鈴木"]
scores = [85, 92, 78]
grades = ["B", "A", "C"]
for name, score, grade in zip(names, scores, grades):
print(f"{name}さん: {score}点 ({grade})")
# 実行結果:
# 田中さん: 85点 (B)
# 佐藤さん: 92点 (A)
# 鈴木さん: 78点 (C)
注意点: リストの長さが異なる場合、短い方に合わせて終了します。全要素を処理したい場合はitertools.zip_longest()を使いましょう。
names = ["田中", "佐藤", "鈴木", "山田"]
scores = [85, 92] # 2件しかない
# zip()は短い方に合わせて終了
for name, score in zip(names, scores):
print(f"{name}さん: {score}点")
# 実行結果:
# 田中さん: 85点
# 佐藤さん: 92点
# ※ 鈴木、山田は処理されない
from itertools import zip_longest
names = ["田中", "佐藤", "鈴木", "山田"]
scores = [85, 92]
# zip_longest()は長い方に合わせる(足りない部分はNone)
for name, score in zip_longest(names, scores):
print(f"{name}さん: {score}点")
# 実行結果:
# 田中さん: 85点
# 佐藤さん: 92点
# 鈴木さん: None点
# 山田さん: None点
# fillvalueで埋める値を指定できる
for name, score in zip_longest(names, scores, fillvalue=0):
print(f"{name}さん: {score}点")
# 実行結果:
# 田中さん: 85点
# 佐藤さん: 92点
# 鈴木さん: 0点
# 山田さん: 0点
5. リスト内包表記
for文を1行で書く方法です。新しいリストを作成する時にとても便利です。
基本形
通常のfor文で書くと4行必要な処理が、内包表記なら1行で済みます。
numbers = [1, 2, 3, 4, 5]
doubled = []
for n in numbers:
doubled.append(n * 2)
print(doubled)
# 実行結果:
# [2, 4, 6, 8, 10]
numbers = [1, 2, 3, 4, 5]
doubled = [n * 2 for n in numbers]
print(doubled)
# 実行結果:
# [2, 4, 6, 8, 10]
条件付き(if)
条件に合う要素だけを抽出できます。フィルタリング処理に便利です。
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
evens = [n for n in numbers if n % 2 == 0]
print(evens)
# 実行結果:
# [2, 4, 6, 8, 10]
large_numbers = [n for n in numbers if n > 5]
print(large_numbers)
# 実行結果:
# [6, 7, 8, 9, 10]
変換付き
要素を変換しながら新しいリストを作れます。
names = ["tanaka", "sato", "suzuki"]
upper_names = [name.upper() for name in names]
print(upper_names)
# 実行結果:
# ['TANAKA', 'SATO', 'SUZUKI']
name_lengths = [len(name) for name in names]
print(name_lengths)
# 実行結果:
# [6, 4, 6]
辞書からの値抽出
辞書のリストから特定のキーの値だけを抽出する、という使い方もよくあります。
students = [
{"name": "田中", "score": 85},
{"name": "佐藤", "score": 92},
{"name": "鈴木", "score": 78}
]
names = [s["name"] for s in students]
print(names)
# 実行結果:
# ['田中', '佐藤', '鈴木']
high_scorers = [s["name"] for s in students if s["score"] >= 80]
print(high_scorers)
# 実行結果:
# ['田中', '佐藤']
6. 辞書内包表記
リスト内包表記の辞書版です。キーと値のペアを持つ辞書を1行で作成できます。
students = [
{"name": "田中", "score": 85},
{"name": "佐藤", "score": 92},
{"name": "鈴木", "score": 78}
]
name_to_score = {s["name"]: s["score"] for s in students}
print(name_to_score)
# 実行結果:
# {'田中': 85, '佐藤': 92, '鈴木': 78}
print(name_to_score["佐藤"])
# 実行結果:
# 92
7. else節
pythonのfor文にはelse節を付けられます。ループがbreakせずに最後まで完了した時に実行されます。
numbers = [1, 3, 5, 7, 9]
for n in numbers:
if n % 2 == 0:
print(f"偶数が見つかりました: {n}")
break
else:
print("偶数は見つかりませんでした")
# 実行結果:
# 偶数は見つかりませんでした
breakした場合はelse節が実行されません。
numbers = [1, 3, 4, 7, 9]
for n in numbers:
if n % 2 == 0:
print(f"偶数が見つかりました: {n}")
break
else:
print("偶数は見つかりませんでした")
# 実行結果:
# 偶数が見つかりました: 4
「見つからなかった」というフラグ変数を用意しなくて済むので、検索処理がスッキリ書けます。
8. 非同期for文(async for)
非同期処理でイテレーションする時に使用します。Webスクレイピングや外部API呼び出しなど、I/O待ちが発生する処理で利用できます
import asyncio
async def fetch_data(id):
await asyncio.sleep(0.1) # 擬似的な非同期処理
return f"データ{id}"
async def main():
# 非同期ジェネレータを使う例
async def data_generator():
for i in range(3):
data = await fetch_data(i)
yield data
async for data in data_generator():
print(data)
asyncio.run(main())
# 実行結果:
# データ0
# データ1
# データ2
おわりに
for文のパターンを整理してみました。パターンが多く混乱しますが、よく利用するのは以下の4パターンだと思います。
- 基本のfor文 - 最も基本
- enumerate() - インデックスが必要な時に
- リスト内包表記 - 新しいリストを作る時に
- break/continue - ループの流れを制御したい時に
JISOUのメンバー募集中!
プログラミングコーチングJISOUでは、新たなメンバーを募集しています。
日本一のアウトプットコミュニティでキャリアアップしませんか?
興味のある方は、ぜひホームページをのぞいてみてください!
▼▼▼
https://projisou.jp