Python
python3

Python のイテラブル、イテレータ、ジェネレータ: 用語の整理と公式資料へのリンク集

この記事はイテレータでもあるジェネレータの属性に焦点を当てて情報を整理したものです。

使い方には触れていません。使い方は公式ドキュメントに豊富な説明があるので、後半のリンク集がお役に立てればと思います。

この記事内にあるリンク先はすべて公式ドキュメントです。

用語

イテラブル(反復可能オブジェクト) iterable

collections.abc.Iterable によるイテラブルの判別が失敗する例(シーケンスプロトコル)。

from collections.abc import Iterable


class SequenceProtocol(object):
    def __init__(self):
        self.values = [True]

    def __getitem__(self, key):  # シーケンスプロトコルの条件:
        return self.values[key]  # __getitem__() メソッドがあり、その引数に 0 を渡すと値を返す。 


def isiterable(instance):
    try:
        iter(instance)
    except TypeError:
        return False
    else:
        return True


inst = SequenceProtocol()
print("__iter__:", hasattr(inst, '__iter__'))
print("iter(inst):", isiterable(inst))
print("Iterable:", isinstance(inst, Iterable))

for item in inst:
    print(item)
__iter__: False
iter(inst): True
Iterable: False
for: True

イテレータ iterator

  • イテラブル。iter() に渡すと自分自身(イテレータ)が返ってくる。
    • ジェネレータ(関数ではなく生成したイテレータ)を渡すとジェネレータが返ってくる。
    • つまり、iter() の返すものは必ずイテレータ。
  • 組み込み関数 next() に渡すと値を一つずつ返す。返す値がなければ StopIteration 例外を送出。
  • 判別は __iter____next__ の有無を hasattr() することで可能(イテレータプロトコル)。

ジェネレータ generator

  • ジェネレータは、ジェネレータ関数か、もしくはジェネレータイテレータのこと
    • どちらを指すのかは文脈で変わる
    • この記事では「ジェネレータ関数」と「ジェネレータ(ジェネレータイテレータ)」と書き分け。

ジェネレータ関数 generator function

  • yieldを持つ関数。呼び出すと yield 式の値を一つずつ返すジェネレータを生成。
    • ジェネレータは yield して値を返してもローカル変数を保持。前回の yield 式から実行を再開可能。
    • ジェネレータがコードの最後まで yield がなく関数を抜けると StopIteration 例外を送出。
    • yield from にジェネレータを渡すとそのジェネレータの yield が直結したかのように振る舞う。
      • yield from 式にイテラブルを渡して値を取り出していくことも可能。
  • 判別は inspect.isgeneratorfunction() で可能。

ジェネレータイテレータ generator iterator

早見表

用語 英語 for
iter()
next() send() 判定手段
イテラブル
反復可能オブジェクト
iterable 不可 不可 iter(inst)
イテレータ iterator 不可 collection.abc.Iterator
__iter____next__
ジェネレータイテレータ generator iterator collection.abc.Generator
inspect.isgenerator
__iter____next__send
ジェネレータ関数 generator function 不可 不可 不可 inspect.isgeneratorfunction

公式ドキュメントへのリンク集

チュートリアル、HOWTO、用語集

What's New、PEP

標準ライブラリ、言語リファレンス

付記

  • async 関係も整理する候補にありましたが、結局は避けて通りました。

    • 調べていて面白かったのですが、書く量が増えすぎて扱い切れませんでした。
  • 公式ドキュメントの有り難さを改めて感じました。著者や訳者の方々に感謝です。

  • 2018/05/06

    • 元々記事の作成理由がジェネレータだったので、趣旨を明確にするため全体的に見直し。
    • 用語の加筆修正
      • 「ジェネレータ関数」と「ジェネレータ」の書き分けを明記。
      • ジェネレータ関数の項に return の振る舞い、yield from 式を追加
      • ジェネレータイテレータの項に throw() と close() を追加。
    • リンク集に追加
      • PEP の項を追加。PEP の項に「PEP 343 -- The "with" Statement」を追加
      • 標準ライブラリ inspect の項に追加: ジェネレータおよびコルーチンの現在の状態
  • 2018/05/06

    • 用語の各項と早見表に判定手段を追加。