この記事では、Pythonでのジェネレータとイテレータの活用場面、およびそれらの違いについて詳しく解説します。具体的なコード例とその解説、応用例を3つ以上含めています。
目次
ジェネレータとは
ジェネレータは、イテレータの一形態であり、一度にすべての要素を生成するのではなく、一つずつ要素を生成できる仕組みです。これは、メモリを節約しながら大規模なデータを処理する場合に非常に便利です。
基本的なジェネレータの作り方
def my_generator():
yield 1
yield 2
yield 3
for i in my_generator():
print(i)
このコードでは、`my_generator`関数は`yield`ステートメントを使用して3つの値を一つずつ返します。この関数を用いてループ処理を行うと、1, 2, 3という数値が順に出力されます。
イテレータとは
イテレータは、`__iter__()`と`__next__()`メソッドを実装したオブジェクトです。ジェネレータよりも汎用性が高く、より複雑な状態を持つことができます。
基本的なイテレータの作り方
class MyIterator:
def __init__(self, start, end):
self.value = start
self.end = end
def __iter__(self):
return self
def __next__(self):
if self.value >= self.end:
raise StopIteration
self.value += 1
return self.value - 1
for i in MyIterator(1, 3):
print(i)
このコード例では、`MyIterator`クラスが`__iter__`と`__next__`メソッドを持っています。このイテレータは、指定された開始値と終了値の間でイテレーションを行います。
ジェネレータとイテレータの違い
主な違いは、ジェネレータは関数として定義され、`yield`ステートメントで要素を返すのに対し、イテレータはクラスとして定義され、`__next__()`メソッドで要素を返す点です。
メモリ使用量
ジェネレータは要素を一つずつ生成するので、イテレータよりもメモリ使用量が少なくなる場合が多いです。
柔軟性
イテレータはより複雑な状態を持つことができるので、柔軟性が高いと言えます。
応用例
ファイルの行を順番に読み込む(ジェネレータ)
def read_large_file(file_path):
with open(file_path, 'r') as f:
for line in f:
yield line.strip()
for line in read_large_file('large_file.txt'):
print(line)
フィボナッチ数列(イテレータ)
class Fibonacci:
def __init__(self):
self.a, self.b = 0, 1
def __iter__(self):
return self
def __next__(self):
self.a, self.b = self.b, self.a + self.b
return self.a
fibo = Fibonacci()
for i, value in enumerate(fibo):
if i > 9:
break
print(value)
CSVファイルのパーサ(イテレータ)
import csv
class CSVParser:
def __init__(self, file_path):
self.file_path = file_path
def __iter__(self):
self.csv_file = open(self.file_path, 'r')
self.reader = csv.reader(self.csv_file)
return self
def __next__(self):
row = next(self.reader, None)
if row is None:
self.csv_file.close()
raise StopIteration
return row
for row in CSVParser('data.csv'):
print(row)
まとめ
ジェネレータとイテレータは、それぞれ特有の特性と利点があります。どちらを使用するかは、目的や要件によって異なります。この記事を通じて、それぞれの違いと活用例について理解できたでしょうか。
コメント