Pythonにおけるイテレータ、ジェネレータ、リスト内包表記、ジェネレータ式の実践的解説

イテレータの仕組み

イテレータはPythonの反復処理における基盤となる概念です。イテレータオブジェクトは__iter__()__next__()メソッドを実装しており、順次データにアクセスするためのプロトコルを提供します。

反復可能オブジェクトとイテレータの違い

反復可能オブジェクトは__iter__()メソッドを持ちますが、__next__()メソッドがないため直接値を取得できません。反復可能オブジェクトからイテレータを取得するには__iter__()メソッドを使用します。

sample_set = {10, 20, 30, 40, 50}
iterator_obj = sample_set.__iter__()
print(iterator_obj)

実行結果: <set_iterator object at 0x0000000001EF1480>

値の取得とStopIteration例外

イテレータから値を取得するには__next__()メソッドを使用します。すべての要素を取得した後にさらに__next__()を呼び出すとStopIteration例外が発生します。

num_set = {10, 20, 30, 40, 50}
iterator = num_set.__iter__()

for _ in range(5):
    print(iterator.__next__())

イテレータの判定方法

オブジェクトがイテレータかどうかを判定する方法:

from collections.abc import Iterator, Iterable

data_list = [1, 2, 3, 4]
print(f"反復可能オブジェクト: {isinstance(data_list, Iterable)}")
print(f"イテレータ: {isinstance(data_list, Iterator)}")

# ファイルハンドルはイテレータ
with open('test.txt', 'w') as file:
    print(f"ファイルハンドルがイテレータ: {isinstance(file, Iterator)}")

ジェネレータの実装

ジェネレータは特殊なタイプのイテレータで、関数ベースで作成されます。yield文を使用して値を返し、関数の実行状態を保持します。

def number_generator():
    yield 100
    yield 200
    yield 300
    yield 400

gen = number_generator()
print(next(gen))  # 100
print(next(gen))  # 200

send()メソッドの使用

ジェネレータはsend()メソッドを使って値を送信できますが、最初のyieldはnext()で開始する必要があります。

def interactive_generator():
    value_a = yield "最初の値"
    print(f"受信値: {value_a}")
    value_b = yield "次の値"
    print(f"受信値: {value_b}")
    yield "最終値"

gen_obj = interactive_generator()
print(next(gen_obj))           # 最初のyield
print(gen_obj.send("テストデータ1"))
print(gen_obj.send("テストデータ2"))

リスト内包表記

リスト内包表記はリストを簡潔に生成するための構文です。従来のforループよりも読みやすく、効率的です。

# 基本的なリスト内包表記
numbers = [x for x in range(1, 11)]
print(numbers)  # [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

# 条件付きフィルタリング
even_numbers = [x for x in range(20) if x % 2 == 0]
print(even_numbers)  # [0, 2, 4, 6, 8, 10, 12, 14, 16, 18]

ネストしたリストの処理

name_lists = [['Tom', 'Billy', 'Jefferson', 'Andrew'],
              ['Alice', 'Jennifer', 'Sherry', 'Eva']]

# 複数リストからの条件付き選択
selected_names = [name for sublist in name_lists 
                 for name in sublist if name.count('e') >= 2]
print(selected_names)  # ['Jefferson', 'Jennifer']

ジェネレータ式

ジェネレータ式はリスト内包表記と似ていますが、括弧を使用し、メモリ効率の良い遅延評価を行います。

# ジェネレータ式の作成
gen_expr = (x * 2 for x in range(5))
print(gen_expr)  # <generator object <genexpr> at 0x...>

# 値の取得
for value in gen_expr:
    print(value)  # 0, 2, 4, 6, 8

ジェネレータ式は大規模なデータ処理時にメモリ使用量を抑えるのに有効です。

タグ: Python イテレータ ジェネレータ リスト内包表記 ジェネレータ式

6月1日 16:00 投稿