Pythonの技法:ジェネレータを用いた遅延リストの構築

文:Nick Gibson(Builder AU)  翻訳校正:原井彰弘
2008-01-17 15:00:00
  • このエントリーをはてなブックマークに追加

 ジェネレータは本質的には反復子と同じである。従って、さまざまな式の中で(リストのような)シーケンスの代わりにジェネレータを用いることが可能である。たとえば、上記の例のような書き方をする代わりに、以下のような簡単な書き方をしてもよい。

>>> gen2 = generator1()
>>> for i in gen2:
...     print i
... 
first
second
third

 また、以下のようにして一発でジェネレータをリストに変換することも可能である。

>>> gen3 = generator1()
>>> list(gen3)
['first', 'second', 'third']

 それでは、実際にジェネレータが役立つような例を次に挙げてみよう。以下に「組み合わせ」を作成する関数をきわめて一般的な方法で記述した。ここでいう組み合わせとは、1つのシーケンスを2つのシーケンスに分割する場合の分割の仕方の数である。

def combination(seq, length):
if not length: return [[]]
else:
l = []
for i in xrange(len(seq)):
for result in combination(seq[i+1:], length-1):
l += [[seq[i]]+result]
return l

 このコードを実行すると、以下のようになる。

>>> combination("ABCDE", 3)
[['A', 'B', 'C'], ['A', 'B', 'D'], ['A', 'B', 'E'], ['A', 'C', 'D'], ['A', 'C', 'E'], ['A', 'D', 'E'], ['B', 'C', 'D'], ['B', 'C', 'E'], ['B', 'D', 'E'], ['C', 'D', 'E']]
>>> combination("ABCDE", 2)
[['A', 'B'], ['A', 'C'], ['A', 'D'], ['A', 'E'], ['B', 'C'], ['B', 'D'], ['B', 'E'], ['C', 'D'], ['C', 'E'], ['D', 'E']]
>>> combination("ABCDE", 5)
[['A', 'B', 'C', 'D', 'E']]

 さて、これをジェネレータを用いたバージョンに変更してみよう。これはただ単に、結果リストに値を追加する処理を行っているコードを、yield文に置き換えれるだけでよい。

def xcombination(seq,length):
if not length: yield []
else:
for i in xrange(len(seq)):
for result in xcombination(seq[i+1:], length-1):
yield [seq[i]]+result
このサイトでは、利用状況の把握や広告配信などのために、Cookieなどを使用してアクセスデータを取得・利用しています。 これ以降ページを遷移した場合、Cookieなどの設定や使用に同意したことになります。
Cookieなどの設定や使用の詳細、オプトアウトについては詳細をご覧ください。
[ 閉じる ]