概要
緑さん「ふふーん。今日はジェネレータを作って遊んじゃうぜ。いやー、これはレベル高いぜ」
def my_generator():
yield "最初の文字列"
yield "次の文字列"
yield "最後の文字列"
緑さん「ふふーん。レベル高いから、型も書いちゃおうかなー。ま、まあここは ChatGPT ちゃんにお願いしよう (震え声)」
from collections.abc import Generator
def my_generator() -> Generator[str, None, None]:
yield "最初の文字列"
yield "次の文字列"
yield "最後の文字列"
緑さん「ハァ?! なんだ str
のあとの None, None
って……?!」
1日1 Python のお時間です。
みっつの型の説明が書いてあるとこ
A generator can be annotated using the generic type Generator[YieldType, SendType, ReturnType].
みっつの型は、 YieldType, SendType, ReturnType っていうのね。
YieldType と ReturnType はまあ簡単
- YieldType が yield で返すやつ
- ReturnType が return で返すやつ (= StopIteration に持たせる値)
# NOTE: よく from typing import Generator と書かれるけど、それは非推奨ってここ↓に書いてある。
# https://docs.python.org/ja/3/library/typing.html#typing.Generator
from collections.abc import Generator
# YieldType (yield で返す値)
# ReturnType (return で返す値)
# ……を埋めたもの。
def my_generator() -> Generator[str, None, int]:
yield "最初の文字列"
yield "次の文字列"
return 999 # return すると StopIteration の値になる
gen = my_generator()
try:
print(next(gen)) # --> 最初の文字列
print(next(gen)) # --> 次の文字列
print(next(gen)) # --> StopIteration(999)
except StopIteration as e:
print(e.value) # --> return の値: 999
SendType がムズい
from collections.abc import Generator
# SendType (send で受け取る値)
def my_generator() -> Generator[str, int, None]:
# まず next して、その次に send した値が、 yield の返り値になる。
received = yield "最初の文字列"
yield str(received)
gen = my_generator()
print(next(gen)) # --> '最初の文字列'
print(gen.send(123)) # --> '123'
まず next して、その次に send した値が、 yield の返り値になる。
いやもう、 yield は出力だけをするもの、と理解している緑さんにとって “yield の返り値” っていうフレーズがもうムズい。さらに……
- 最初っから
send(123)
は不可能。 (send → send は基本、不可能。) - でも
send(None)
なら OK。 (send(None) → send は OK。)
……というような隠れ仕様もムズい。なかなかよい Python コア知識をゲットしちゃったね。
send のドキュメントはこちら↓
おしまい
ジェネレータとの出会いはおよそ9年前。
当時は yield だけに圧倒されていたが、現在では Generator さんとの間合いを詰め、 send とかいうバケモンと鍔迫り合いができるくらいにはなったか。