kb84tkhrのブログ

何を書こうか考え中です あ、あと組織とは関係ないってやつです 個人的なやつ

ジェネレータ(続き)

何をすればわかった感が出るんだろうか
それもわからないのでランダムにいろいろ試してみよう

returnはどうなるんだろうか

def gen():
    yield "abc"
    yield "def"
    return 3

genを呼んでも3が返されるわけじゃないし・・・

>>> g = gen()
>>> next(g)
'abc'
>>> next(g)
'def'
>>> next(g)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration: 3

StopIterationの値(?)になるのか
なるほど

書いてあった

Built-in Exceptions — Python 3.7.3rc1 documentation

When a generator or coroutine function returns, a new StopIteration instance is raised, and the value returned by the function is used as the value parameter to the constructor of the exception.

forとか使ってる分には関係ない?

>>> for s in gen():
...     print(s)
...
abc
def
>>> [s for s in gen()]
['abc', 'def']

まあ関係ないよね
どんな使いみちがあるかな
自分でnext()使って回さないと使わなさそうだし

そういえばgen()の型って何になるの
ジェネレータを返すわけだから・・・

mypyに厳しく見てもらったら何か教えてくれないだろうか

$ mypy --strict practice.py
practice.py:1: error: Function is missing a type annotation

厳しいだけか
調べるか

PEP 483に書いてあった

The return type of generator functions can be annotated by the generic type Generator[yield_type, send_type, return_type] provided by typing.py module:

なるほど
yieldする型と、sendされる型、returnする型を全部指定するのね

そういえばsend()を試すつもりで忘れてる
まずはそこからだ
型の違いがわかりやすいようにこの前のやつをちょっと改造

def gen():
    print("first yield", (yield 1.0))
    print("second yield", (yield 2.0))
    print("third yield", (yield 3.0))
    return "returning"

こうかな

>>> g = gen()
>>> g.send(1)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: can't send non-None value to a just-started generator

おっと
いきなりsend()はダメなのか

「実行はgeneratorのメソッドが呼ばれた時点ではじまり、
最初のyieldまで進み、generatorの呼び出し元に値を返して
実行を中断する」から
「再度generatorのメソッドを呼ぶと、yieldがあたかも
関数呼び出しであったかのように実行が継続する」だから
yieldが返すのは「再度」呼び出したメソッドから渡されたもの
ってわけだな
ややこし

>>> g = gen()
>>> next(g)
1.0

「実行はgeneratorのメソッドが呼ばれた時点ではじまり、
最初のyieldまで進み、generatorの呼び出し元に値を返して
実行を中断する」

>>> g.send(1)
first yield 1
2.0

「再度generatorのメソッドを呼ぶと、yieldがあたかも
関数呼び出しであったかのように実行が継続する」

>>> g.send(2)
second yield 2
3.0
>>> g.send(3)
third yield 3
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration: returning

わかってきた
かな
どうかな