2009-05-12 32 views
2

ちょっと、私は再帰的ジェネレータを使って数値の固定整数パーティションを作成していましたが、スコープの問題で混乱しました。Python再帰的ジェネレータのスコープ

コードはこのスニペットに似ています。

def testGen(a,n): 
    if n <= 1: 
     print('yield', a) 
     yield a 
    else: 
     for i in range(2): 
      a[i] += n 
      for j in testGen(a,n-i-1): 
       yield j 

私の混乱は以下のとおりです。

>>> list(testGen([1,2],4)) 
yield [10, 2] 
yield [10, 4] 
yield [10, 7] 
yield [12, 11] 
yield [12, 13] 
[[12, 13], [12, 13], [12, 13], [12, 13], [12, 13]] 

私は単純に(例えば、再帰呼び出しにa[:]に渡す)配列のコピーを使用して正しい答えを得ることができますが、私はまだ上記の動作を理解していません。 印刷文と利回りの値が異なるのはなぜですか?

答えて

2

printステートメントは、特定の時点のリストを表示します。コードを実行するときにコードがリストを変更するので、最後にリストを調べるときにその値が表示されます。

あなたはを通して踏んでこれを観察することができます。

>>> g = testGen([1,2],4) 
>>> g.next() 
('yield', [10, 2]) # note brackets in print statement because I'm on python 2.5 
[10, 2] 
>>> g.next() 
('yield', [10, 4]) 
[10, 4] 
>>> g.next() 
('yield', [10, 7]) 
[10, 7] 
>>> g.next() 
('yield', [12, 11]) 
[12, 11] 
>>> g.next() 
('yield', [12, 13]) 
[12, 13] 
2

私はあなたがそれが特定の値を持って印刷するときに、あなたはそれを印刷し、次の時間が実際にように値を更新し、している、配列を変異されていると思います。最後に、同じ配列への5つの参照があるので、もちろん同じ値を5回持ちます。

+0

'[I] + = N 'は確か配列を変異させます。 –

0

あなたは2つの収量を持っているときにのみ1つのprint文を持っているので、印刷や歩留まりの文が異なっています。これを試してください:

def testGen(a,n): 
    if n <= 1: 
     print('yield', a) 
     yield a 
    else: 
     for i in range(2): 
      a[i] += n 
      for j in testGen(a,n-i-1): 
       print('yield', j) 
       yield j 

>>> list(testGen([1,2],4)) 
('yield', [10, 2]) 
('yield', [10, 2]) 
('yield', [10, 2]) 
('yield', [10, 2]) 
('yield', [10, 4]) 
('yield', [10, 4]) 
('yield', [10, 4]) 
('yield', [10, 4]) 
('yield', [10, 7]) 
('yield', [10, 7]) 
('yield', [10, 7]) 
('yield', [12, 11]) 
('yield', [12, 11]) 
('yield', [12, 11]) 
('yield', [12, 13]) 
('yield', [12, 13]) 
('yield', [12, 13]) 
[[12, 13], [12, 13], [12, 13], [12, 13], [12, 13]] 

コピーを作成するのではなく、同じリストを回ってきたので、最後の収量はあなたの答えです。リストに渡す場合

2

リストは、変更可能なオブジェクトであり、発電機は、リストに最終的にすべての参照は同じリストを指しますが、そのリストにインプレース操作を実行します。

関連する問題