Python で無限シーケンスを作る
ジェネレータを使うと、終わりのない「無限シーケンス」を作ることができます。すべての要素をメモリに保持する必要がないため、理論上は永遠に続くシーケンスも表現できます。
基本的な無限シーケンス
永遠にカウントアップするジェネレータを作ってみましょう。
def count_forever(start=0):
n = start
while True:
yield n
n += 1
counter = count_forever()
print(next(counter)) # 0
print(next(counter)) # 1
print(next(counter)) # 2
# 呼び続ける限り永遠に続く
無限シーケンスの活用
無限シーケンスは、必要な数だけ取り出して使います。
from itertools import islice
def count_forever(start=0):
n = start
while True:
yield n
n += 1
# 最初の5個だけ取り出す
first_five = list(islice(count_forever(), 5))
print(first_five) # [0, 1, 2, 3, 4]
# 10番目から15番目まで取り出す
some_numbers = list(islice(count_forever(), 10, 15))
print(some_numbers) # [10, 11, 12, 13, 14]
実用的な無限シーケンス
いくつかの実用的な例を見てみましょう。
# フィボナッチ数列(無限)
def fibonacci():
a, b = 0, 1
while True:
yield a
a, b = b, a + b
# 最初の10個
from itertools import islice
print(list(islice(fibonacci(), 10)))
# [0, 1, 1, 2, 3, 5, 8, 13, 21, 34]
# 素数列(無限)
def primes():
def is_prime(n):
if n < 2:
return False
for i in range(2, int(n ** 0.5) + 1):
if n % i == 0:
return False
return True
n = 2
while True:
if is_prime(n):
yield n
n += 1
print(list(islice(primes(), 10)))
# [2, 3, 5, 7, 11, 13, 17, 19, 23, 29]
サイクルシーケンス
要素を無限に繰り返すシーケンスも作れます。
def cycle(iterable):
items = list(iterable)
while True:
for item in items:
yield item
colors = cycle(["赤", "青", "緑"])
for i, color in enumerate(colors):
if i >= 7:
break
print(color, end=" ")
# 赤 青 緑 赤 青 緑 赤
条件付きで停止する
無限シーケンスでも、条件を満たしたら停止できます。
def count_forever():
n = 0
while True:
yield n
n += 1
# 条件を満たすまで取り出す
for n in count_forever():
if n > 100:
break
if n % 15 == 0:
print(n, end=" ")
# 0 15 30 45 60 75 90
itertools の無限イテレータ
標準ライブラリの itertools には、便利な無限イテレータが用意されています。
from itertools import count, cycle, repeat
# count: 無限カウント
for n in count(10, 2): # 10から2ずつ
if n > 20:
break
print(n, end=" ")
# 10 12 14 16 18 20
# repeat: 同じ値を繰り返す
for x in repeat("A", 3): # 3回だけ
print(x, end=" ")
# A A A
無限シーケンスは、ストリームデータの処理、シミュレーション、数学的なシーケンスの表現などに便利です。ただし、list() で変換しようとすると永遠に終わらないので、必ず islice() や条件付きの break で取り出す量を制限してください。