sec03 - Python forループの実践ガイド|enumerate・sorted・zipなどの便利関数を徹底解説
スポンサーリンク

forループで使える便利な関数

forループでイテラブルなオブジェクト(listやrangeなど)を扱う際、単純に要素を順に取り出すだけでなく、組み込み関数やitertoolsのユーティリティを組み合わせることで、より効率的で、かつ可読性の高いコードが書けます。ここでは各関数の「何を返すか」「forブロック内ではどう受け取るか」「注意点」を丁寧に説明し、サンプルコードと実行結果(コードブロック)を示します。

1. enumerate()

enumerate()は、イテラブルの各要素に対応するインデックス(数値)と要素自身を、順に含むtuple(index, item)を返すイテレータ(反復子)を生成します。forで使うときはアンパックを使ってindexitemを受け取るのが一般的です。start引数でインデックスの開始値を指定できます。

items = ['apple','banana','cherry']

# enumerateは (index, item) のtupleを返すイテレータを生成する
for index, item in enumerate(items, start=1):
    print(f'{index}番目のアイテムは{item}です')
1番目のアイテムはappleです
2番目のアイテムはbananaです
3番目のアイテムはcherryです

注意点:返されるのはイテレータ(lazy)なので、必要であればlist(enumerate(iterable))でlist化できますが、通常はforで順次処理するのがメモリ効率的です。

スポンサーリンク

2. sorted()

sorted()はイテラブルをソートした新しいlistを返します。元のオブジェクトは変更されません。デフォルトは昇順ですが、reverse=Trueを指定すると降順になります。複雑な基準でソートする場合はkey=引数(例:key=lambda x: x[1])を使います。

numbers = [5, 2, 9, 1]

# 昇順でループ(sortedは新しいlistを返す)
for num in sorted(numbers):
    print(f'数字は{num}です')

# 降順でループ(reverse=Trueを指定)
for num in sorted(numbers, reverse=True):
    print(f'降順の数字は{num}です')
数字は1です
数字は2です
数字は5です
数字は9です
降順の数字は9です
降順の数字は5です
降順の数字は2です
降順の数字は1です

注意点:ソート結果は新しいlistとして返るため、元データの順序を保持したまま処理できます。大規模データを頻繁にソートすると処理コストが増大するため、必要な範囲だけソートする工夫が有効です。

3. reversed()

reversed()はシーケンス(list・tuple・文字列など)を逆順に返すイテレータを生成します。元のシーケンス自体は変更されません。forで使うときは単に受け取って処理します。

names = ['Alice','Bob','Charlie']

for name in reversed(names):
    print(f'逆順の名前は{name}です')
逆順の名前はCharlieです
逆順の名前はBobです
逆順の名前はAliceです

注意点:reversedはシーケンス型に対して有効です(一般のイテラブルでは使えない場合があります)。必要に応じてlist()で明示的にシーケンス化してから使うこともできます。

4. zip()

zip()は複数のイテラブルから同時に要素を取り出し、各回にtuple(例:(a,b))を返すイテレータを生成します。forでアンパックして使うのが一般的です。ループは最も短いイテラブルに合わせて終了します(余る要素は切り捨てられます)。

names = ['Alice','Bob']
ages = [25, 30, 35]  # agesの方が長い

for name, age in zip(names, ages):
    print(f'{name}の年齢は{age}歳です')
Aliceの年齢は25歳です
Bobの年齢は30歳です

注意点:この例ではagesの方が長いため、最後の35は無視されます。要素数が不揃いのときに余りを保持したい場合は次のzip_longest()を検討してください。

5. itertools.zip_longest()

itertools.zip_longest()zip()と似ていますが、長さの異なるイテラブルを同時にループできます。短い方の不足分にはfillvalueで指定した値が代入されます。返される各回の要素はtupleです。

from itertools import zip_longest

names = ['Alice','Bob','Charlie']
ages = [25, 30]  # agesが短い

for name, age in zip_longest(names, ages, fillvalue='-'):
    print(f'{name}の年齢は{age}歳です')
Aliceの年齢は25歳です
Bobの年齢は30歳です
Charlieの年齢は-歳です

注意点:この例ではCharlieの年齢情報がagesに足りていないため、fillvalue='-'ageに代入されます。fillvalueは任意の値(Noneや文字列など)を指定できます。

6. itertools.chain()

itertools.chain()は複数のイテラブルを連結して一つのイテラブルとして扱えるイテレータを返します。listやtupleなどデータ構造が異なっていてもそのまま渡せるため、事前にすべてを同じデータ構造に変換する必要がありません。forで単純に順番に要素を処理できます。

from itertools import chain

list1 = [1, 2]
tuple1 = (3, 4)
set1 = {5, 6}  # setの順序は保証されない点に注意

for num in chain(list1, tuple1, set1):
    print(f'要素は{num}です')
要素は1です
要素は2です
要素は3です
要素は4です
要素は5です
要素は6です

注意点:上の例ではsetを含めていますが、setは順序を持たないため出力順が環境によって変わる可能性があります。順序が重要な場合は、順序を持つイテラブル(listやtuple)を使用するか、事前にソートしてください。

スポンサーリンク