Python プログラミング メモ

イテレータとジェネレータについて

イテレータとジェネレータについて

 

以前、ジェネレータの例についてブログにメモをしておきました。

no image
ジェネレータ

ジェネレータ 関数の処理の途中で中断して、yieldを使う事で関数外の処理を実施しても、再びyieldの次から再開できる。 どうやったら効果を発揮するのだろうか? 実装例 def gen(): pri ...

続きを見る

 

が、今、振り返ると私自身、ジェネレータの意味が良く理解できていない事がわかりました。

再度、ジェネレータについて考えてみたいと思っています。

そして、ジェネレータを理解するにはイテレータから理解する必要があるという事もわかりました。

 

イテレータ

 

まず、イテレータとは何でしょうか?

イテレータとは、連続するデータを操作するオブジェクトの事です。

連続するデータとは例えば、リストや集合、タプルなどですね。

 

例えば連続データを処理する時に、100万件のレコードを処理する必要があったケースをイメージしてみます。

一度、100万件のレコードを全部取り込んだ後に処理するよりも、1件ずつレコードを処理して処理後に破棄、また次のレコードを取り込んで処理後に破棄。

このような処理を行った方が効率が良いケースがあります。

こういった場合にイテレータを利用するとPythonの枠組みの中で便利だったりするわけです。

 

例えば、for 文を使う事が多々あると思うのですが、実は for 文の裏側で動いているのがイテレータです。

以下は for 文を自作した例です。

l = [1, 2, 3, 4, 5]
iterator = iter(l)
try:
    l1 = next(iterator)
    print(l1)
    l2 = next(iterator)
    print(l2)
    l3 = next(iterator)
    print(l3)
    l4 = next(iterator)
    print(l4)
    l5 = next(iterator)
    print(l5)
    l6 = next(iterator)
    print(l6)
except StopIteration:
    print("ループが終了します。")

リスト l の要素を、iter 関数を利用して変数 iterator に代入しました。

その後、next 関数で順番に1つ1つ要素を代入して出力しています。

今回の例では、要素が5つしかないので、6つ目の要素を代入しようとした時に例外 StopIteration が発生した為、ループが終了する事になります。

これが for 文の仕組みです。

ちなみにPythonは、 「__next__() と __iter__() メソッドを持っているオブジェクトをイテレータである。」と定義しています。

変数 iterator を dir 関数で対象の属性を出力してみると以下の結果が確認できます。

[

    '__class__',
    '__delattr__',
    '__dir__',
    '__doc__',
    '__eq__',
    '__format__',
    '__ge__',
    '__getattribute__',
    '__gt__',
    '__hash__',
    '__init__',
    '__init_subclass__',
    '__iter__',
    '__le__',
    '__length_hint__',
    '__lt__',
    '__ne__',
    '__new__',
    '__next__',
    '__reduce__',
    '__reduce_ex__',
    '__repr__',
    '__setattr__',
    '__setstate__',
    '__sizeof__',
    '__str__',
    '__subclasshook__'

]

 

ジェネレータ

 

イテレータの考え方を理解して、ようやくジェネレータに移る事ができます。

ジェネレータとは、「イテレータを簡単に作れる関数」です。

以下にジェネレータを作成してみます。

def generator():
    x = 1
    yield x
    x += 1
    yield x
    x += 1
    yield x
g = generator()

print("next 1 回目")
next(g)
print("next 2 回目")
next(g)
print("next 3 回目")
next(g)

"""
### 出力内容 ###

next 1 回目
next 2 回目
next 3 回目

"""

 

ちゃんと理解するのが難しい部分ではありますが、ジェネレータを理解する上で、イテレータの概念を理解する事は、とても重要な事だと考えております。

 

 

 

 

 

-Python, プログラミング, メモ

Copyright© donguri.pyのblog , 2024 All Rights Reserved.