いざ空のジェネレータを書こうとすると、専用文法は用意されていないことに気づきます。
空の関数を作ってみると、、、
>>> def void(): ... pass ... >>> type(void()) <class 'NoneType'> # NG >>> list(void()) Traceback (most recent call last): # NG File "<stdin>", line 1, in <module> TypeError: 'NoneType' object is not iterableyield キーワードが無いと、そもそもジェネレータになりません。
続いて、yield だけを呼んでみると、、、
>>> def void(): ... yield ... >>> type(void()) <class 'generator'> # OK >>> list(void()) [None] # NGyield に到達するのでサイズが1となってしまいます。
yield を使いつつ、yield に到達させないことで、空のジェネレータを作ることができます。
>>> def void(): ... if False: ... yield # yieldが存在するが到達しない ... >>> type(void()) <class 'generator'> # OK >>> list(void()) [] # OK
別の書き方として、yield 到達前に return させるやり方もあります。
>>> def void(): ... return ... yield # yieldが存在するが到達しない ... >>> type(void()) <class 'generator'> # OK >>> list(void()) [] # OK
おそらく最も華麗な書き方は、yield from を使うやり方です。
>>> def void(): ... yield from () # 空tupleから空ジェネレータを作成 ... >>> type(void()) <class 'generator'> # OK >>> list(void()) [] # OK1行で書けている点がいいですね。ただし、yield from は Python 3.3 からの機能となります。
変化球として、ジェネレータを返す関数を定義するやり方もあります。
>>> def void(): ... return (_ for _ in ()) # この関数はジェネレータをreturnする ... >>> type(void()) <class 'generator'> # OK >>> list(void()) [] # OK
色々試すと、ちょっとした頭の体操になりますね。
0 件のコメント:
コメントを投稿