Pythonでジェネレータとイテレータを活用する方法とその違い

この記事では、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)

まとめ

ジェネレータとイテレータは、それぞれ特有の特性と利点があります。どちらを使用するかは、目的や要件によって異なります。この記事を通じて、それぞれの違いと活用例について理解できたでしょうか。

コメント

コメントする

目次