イテレータの仕組み
イテレータは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
ジェネレータ式は大規模なデータ処理時にメモリ使用量を抑えるのに有効です。