cover_python_cookbook

Python Cookbook [Creating New Iteration Patterns with Generators : ジェネレーターを利用した独自イテレーションパターンの実装] 投稿一覧へ戻る

Tags: Python , Cookbook , generator , iterable , iteration , yield

Published 2020年5月7日19:19 by T.Tsuyoshi

Problem:

range() や reversed() といった組み込み関数とは異なるイテレーションパターンを実装したい。

Solution:

generator 関数を利用して実装します。


例えば、ある範囲内、あるステップ数で浮動小数点数を生成したいなら次のようになるでしょう。


def float_range(start, stop, step):
x = start
while x < stop:
yield x
x += step



こういった関数を利用するには、for ステートメントであるとか、sum() や list() といった内部でイテラブルを利用する他の関数等と一緒に使用します。


for n in float_range(5, 10, 0.5):
print(n)

# 5
# 5.5
# 6.0
# 6.5
# 7.0
# 7.5
# 8.0
# 8.5
# 9.0
# 9.5



list(float_range(0, 1, 0.125))

# [0, 0.125, 0.25, 0.375, 0.5, 0.625, 0.75, 0.875]




関数内に yield ステートメントが含まれていれば、その関数は generator 関数になります。


通常の関数とは異なり、generator 関数はイテレーション操作に反応して機能します。


以下のスニペットは、generator 関数の基本的なメカニズムを理解するためのものです。
python インタラクティブシェルで実行します。


>>> def countdown(n):
... print('{} からカウントダウンを開始します'.format(n))
... while n > 0:
... yield n
... n -= 1
... print('発射!!!!')

>>> c = countdown(3)
>>> c

# <generator object countdown at 0x0000000004D34F48>




↑ generator をインスタンス化しただけでは何もプリントアウトされません。
これは、イテレーション操作が一切行われていないためです。


>>> next(c)
3 からカウントダウンを開始します
3



↑ 最初の yield が実行され値が渡されてきます


>>> next(c)
2



↑ 次の yield の実行


>>> next(c)
1



↑ その次の yield の実行


>>> next(c)
発射!!!!
Traceback (most recent call last):
File "", line 1, in
StopIteration



↑ そのまた次の yield の実行。ここで、イテレーション最後だよ、の例外が発生します


ここで分かることは、generator 関数はイテレーション内で実行される "next" 操作に反応して実行される、ということです。


1回 generator 関数が値を返すと、イテレーションはその場所でストップします。


イテレーション操作に通常利用される for ステートメント等では、こういったことが水面下で自動的に行われているわけです。

この投稿をメールでシェアする

2 comments

Comment 1 by Grady 2020年5月21日15:13

Hola! I've been reading your web site for a while now and finally
got the courage to go ahead and give you a shout out from
Porter Tx! Just wanted to mention keep up the good
job! You've made some decent points there. I checked on the web for more info
about the issue and found most people will go along with your views on this web
site. I have been surfing online more than 4 hours today,
yet I never found any interesting article like yours.
It’s pretty worth enough for me. In my opinion, if all web owners and bloggers made good content as
you did, the internet will be much more useful than ever before.
http://foxnews.org

Comment 2 by Manager 2020年5月21日20:18

Hello, Grady.

I really appreciate your comment, thank you.

Your comment gives me an courage to keep posting.

コメントを追加する(不適切と思われるコメントは削除する場合があります)