ジェネレータ(続き)
何をすればわかった感が出るんだろうか
それもわからないのでランダムにいろいろ試してみよう
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
わかってきた
かな
どうかな