2012-01-03 16 views
3

これは私がインターネット上で見つけたいくつかのコードであり、あまり説明がありません。私はそれがどのように機能するのか不思議です。私はyield[s for s in subsets(S)]の部分を完全に理解していません。どんな洞察も大いに評価されるだろう!Python 3 - [サブセット(S)のs]とyield

def subsets(aList): 

     if aList ==[]: # base case 
      yield [] 
     else: 
      first = aList[0] 
      rest = aList[1:] 
      for ss in subsets(rest): # include first or don't in each 
       yield ss     # subset of rest 
       yield [first]+ss 

print ("\n testing subsets") 
S = ['A','B','C','D','E'] 

ss = [s for s in subsets(S)] 

print ("The subsets of",S,"are:") 

print (ss) 

答えて

4

subsetsはジェネレーターです:あなたがそれを呼び出すと、あなたが反復処理できるオブジェクトを作成します。反復が別の値を要求するたびに、次のyieldステートメントに実行され、その値が生成されます。また、再帰的なので、5つの項目で実行すると、最後の4つで項目が呼び出されます。

したがって、['A']を渡すと、空のリスト[]を渡す第2のジェネレータが作成されます。それは空リストを生成して終了します。主発電機はそれを受け取り、それをもたらす(yield ss)、yield [first]+ss、それは['A']になるでしょう。合計結果:[[], ['A']]

[s for s in subsets(S)]はリストの理解です。それはと同等です: - あなただけ同じことを達成するためにlist(subsets(S))を行うことができ、この場合

ss = [] 
for s in subsets(S) 
    ss.append(s) 

、それは冗長のようなものです。リスト内包表記は、オブジェクトのコレクションのそれぞれに対して何かを実行したい場合、またはそれらをフィルタリングする場合に使用されます。

2

yieldを理解する方法は、単純にreturn文であり、次に関数が呼び出されるときにyield文から実行が続行されるということを想像することです。残高がなくなると、StopIteration例外が発生します。

>>> x = foo() 
>>> for i in x: 
...  print i 
... 
0 
1 
2 
>>> 

単純な例では、物事をクリアする必要があります:forループはちょうど内部そのStopIteration例外をキャッチして扱うため

>>> def foo(): 
...  for i in range(3): 
...   yield i 
... 
>>> x = foo() 
>>> x 
<generator object foo at 0x7f0cd5c30780> 
>>> x.next() 
0 
>>> x.next() 
1 
>>> x.next() 
2 
>>> x.next() 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
StopIteration 
>>> 

をあなたは、反復可能なように発電機を使用することができますサブセットを取得する方法として、より簡単な方法があります。
下記のレシピをご覧ください:

>>> from itertools import chain, combinations 
>>> 
>>> def powerset(iterable): 
...  s = list(iterable) 
...  return chain.from_iterable(combinations(s, r) for r in range(len(s)+1)) 
>>> 
>>> S = ['A','B','C'] 
>>> list(powerset(S)) 
[(), 
('A',), 
('B',), 
('C',), 
('A', 'B'), 
('A', 'C'), 
('B', 'C'), 
('A', 'B', 'C')] 
関連する問題