飽きるまでやります。

私の私による私のためのメモ。内容に一切の責任を負えません。

ジェネレータの話

概要

そろそろジェネレータでも理解しようと思いました.
言語自体の詳細な仕様みたいなことはあまり勉強しないので正確な仕様はググったほうがいいです.

iterator

Pythonにおけるイテレータはだいたい反復可能なオブジェクトのことを指すはずです.
listやtupleやdictやそれらに似た色んなやつですね.
4. 組み込み型 — Python 3.6.5 ドキュメント

ものすごく噛み砕くと

  • __iter__()__next__()を持っている
  • __iter__()でこいつはiterableなオブジェクトですよと宣言する
  • __next__()で次の要素にアクセスできる
  • for文は__iter__()__next__()を勝手に呼んでくれる

generator

オリジナルのiterableなオブジェクトを作りたいときgeneratorを使うようです.
__iter__()__next__()を持ったクラスを作れば良いわけですがめんどくさいのでジェネレータで簡単に作ろうみたいな感じらしいです.yield式を使います.

defで関数を作るときにreturnでなくyieldを使うことでその関数はジェネレータになり,1回値を生成したら中断して呼び出し元に制御が戻るみたいな動きをします.

適当に書いてみる

def myrange(start, stop, step):
    x = start
    while x < stop:
        yield x
        x += step
for i in myrange(0,5,1):
    print(i)

"""
0
1
2
3
4
"""

yieldなしも書いてみる.

class MyRange(object):
    def __init__(self, start, stop, step):
        self.start = start
        self.stop = stop
        self.step = step
    
    def __iter__(self):
        return self
    
    def __next__(self):
        if self.start >= self.stop:
            raise StopIteration()
        value = self.start
        self.start+=self.step
        return value
mr = MyRange(0,3,1)
print(next(mr))
print(next(mr))
print(next(mr))
print(next(mr))

"""
0
1
2
---------------------------------------------------------------------------
StopIteration                             Traceback (most recent call last)
"""

yieldがすごく簡単なのが分かりました.

メリット

メモリの節約なんかに使うそうです.逆に言えば資源を気にしなくて良いときはあんまり使わないんですかね.

終わりに

ジェネレータ完全に理解した.