Remrinのpython攻略日記

python3に入門しました。python3についてあれこれとサンプルコードとか。

ジェネレータ

ジェネレータについて。
 
通常の関数のreturnの部分をyieldとするとジェネレータを自作できる。
  
偶数を生成するジェネレータ

def gene():
    even = 0
    while True:
        yield even
        even += 2
        
e = gene()
for i in range(5):
    print(next(e))

 
素数を生成するジェネレータ

def gen2(start=2, stop=1000000):
    pr = max(1, start - 1)
    while True:
        while pr < stop:
            pr += 1
            if all(pr%x != 0 for x in range(2, int(pr**0.5) + 1)):
                break
        yield pr
g = gen2()
for i in range(10):
    print(next(g), end=" ")
# 2 3 5 7 11 13 17 19 23 29 

 
フィボナッチ数列を生成するジェネレータ

def fib_gene():
    n = 1
    while True:
        f = ((1 + 5**0.5) / 2)**n / 5**0.5 + 0.5
        yield int(f)
        n += 1

f = fib_gene()        
for i in range(10):
    print(next(f), end=" ")
# 1 1 2 3 5 8 13 21 34 55

 
・ジェネレータは無限ループを作れる。
 というか、無限ループに陥ることもある。
 
・値をすべて取り出すとStopIterationのエラーが発生。

def gene():
    week = ["月", "火", "水", "木", "金", "土", "日"]
    for day in week: 
        yield day

day = gene()
for i in range(7):
    print(next(day), end=" ")
# 月 火 水 木 金 土 日 
        
day = gene()
for i in range(15):
    print(next(day), end=" ")
# StopIteration

 
StopIterationを回避するには取り出す個数を確認するか、whileループを使うなど。

def gene():
    week = ["月", "火", "水", "木", "金", "土", "日"]
    while True:
        for day in week: 
            yield day
        
day = gene()
for i in range(15):
    print(next(day), end="")
# 月火水木金土日月火水木金土日月

 
・値の取り出し
 ・next()関数
 ・__next__()メソッド
 ・イテレートする
 ・max(), list()など

・値の代入
 send()