Python の itertools.cycle を徹底解説!無限ループで繰り返し処理をシンプルに

Python の標準ライブラリである itertools は、効率的なイテレータを提供する便利なツールです。その中でも itertools.cycle は、シーケンスを無限に繰り返して処理するための強力な関数です。本記事では、itertools.cycle の基本から応用例、注意点までをわかりやすく紹介します。

bicycle

itertools.cycle とは?

itertools.cycle は、リストやタプル、文字列などのシーケンスを 無限に繰り返しイテレートする イテレータを作成します。以下はその基本的な例です。

import itertools

colors = ['red', 'blue', 'green']
cycled_colors = itertools.cycle(colors)

# 最初の 10 要素を取り出してみます
for _ in range(10):
    print(next(cycled_colors))

出力:

red
blue
green
red
blue
green
red
blue
green
red

itertools.cycle を使用すると、このようにシーケンスが無限に繰り返されます。非常にシンプルで便利な機能ですが、使い方には注意が必要です。


内部構造とメモリ効率

itertools.cycle は、最初にシーケンスをイテレートして要素を キャッシュ に保存します。その後、繰り返し処理を行う際には、このキャッシュされた要素を再利用します。

注意点

  • キャッシュにすべての要素を保存するため、非常に大きなシーケンスを渡すとメモリ使用量が増加する可能性があります。
  • 元のシーケンスが変更されても、キャッシュされたデータは変わらないため、注意が必要です。

実用例で学ぶ itertools.cycle

1. 安全な繰り返し処理

itertools.cycle は無限ループを生成するため、通常は islice() などを使って取り出す回数を制限します。

from itertools import cycle, islice

letters = ['A', 'B', 'C']
cycled_letters = cycle(letters)

# 最初の 5 要素だけ取り出す
result = list(islice(cycled_letters, 5))
print(result)  # ['A', 'B', 'C', 'A', 'B']

2. トグル機能の実装(ON/OFF 切り替え)

UI の状態管理やフラグの切り替えに便利です。

import itertools

toggle = itertools.cycle(['ON', 'OFF'])

for _ in range(6):
    print(next(toggle))

出力:

ON
OFF
ON
OFF
ON
OFF

3. プレイリストのループ再生

音楽プレイヤーのように、リストのアイテムを無限ループで再生する場合にも使えます。

import itertools

playlist = ["Song1", "Song2", "Song3"]
player = itertools.cycle(playlist)

for _ in range(7):
    print("Now playing:", next(player))

出力:

Now playing: Song1
Now playing: Song2
Now playing: Song3
Now playing: Song1
Now playing: Song2
Now playing: Song3
Now playing: Song1

メモリ効率とパフォーマンスの考慮

itertools.cycle は、シーケンスの要素をキャッシュに保存するため、大きなデータセットを渡すとメモリ消費が大きくなる可能性があります。たとえば、数百万要素のリストを無限ループさせる場合は注意が必要です。

ジェネレータを使った回避策

大きなシーケンスの場合、メモリ効率を考慮してジェネレータを使う方法もあります。ただし、通常は itertools.cycle が最適化されているため、こちらを推奨します。

def repeat_forever(sequence):
    while True:
        for item in sequence:
            yield item

repeater = repeat_forever([1, 2, 3])
print(next(repeater))  # 1

空のシーケンスに対する挙動

空のシーケンスを渡した場合でも例外は発生しませんが、next() を呼び出すと None を返します。

import itertools

empty_cycle = itertools.cycle([])
print(next(empty_cycle))  # None

関連する関数の紹介

itertools には、他にも便利な関数がたくさんあります。特に repeat()islice()chain() などは、cycle() と組み合わせて使うとさらに強力です。

from itertools import cycle, islice

# islice() で繰り返し回数を制限
repeated_items = list(islice(cycle([1, 2]), 5))
print(repeated_items)  # [1, 2, 1, 2, 1]

Matplotlib での使用例

グラフ描画で cycle を使うと、色やスタイルを簡単に繰り返すことができます。

import itertools
import matplotlib.pyplot as plt

colors = itertools.cycle(['r', 'g', 'b'])
x = [1, 2, 3]
y = [1, 4, 9]

for i in range(3):
    plt.plot(x, y, color=next(colors), label=f"Line {i + 1}")

plt.legend()
plt.show()

まとめ

  • itertools.cycle は、シーケンスを無限に繰り返すための便利なツールです。
  • 使用する際には、無限ループに注意し、islice などで制限を設けるのが一般的です。
  • UI のトグルやデータのローテーション、グラフ描画など、多くのユースケースで活用できます。
  • メモリ効率には注意が必要ですが、Python 標準ライブラリの関数として最適化されているため、多くの場面で推奨されます。

ぜひ、itertools.cycle を活用して Python コードをよりシンプルで効率的に書いてみてください!

上部へスクロール