2

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

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

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[:]、再帰呼び出しに渡す)が、それでも上記の動作を理解していません。printステートメントとyield値が異なるのはなぜですか?

4

4 に答える 4

2

配列を変更していると思いますので、印刷すると特定の値になり、次に印刷すると実際に値が更新されます。最後に、同じ配列への参照が5つあるので、もちろん同じ値が5回あります。

于 2009-05-12T01:13:36.353 に答える
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]
于 2009-05-12T01:17:26.113 に答える
2

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

于 2009-05-12T01:20:26.110 に答える
0

2つのyieldがあるのに1つのprintステートメントしかないため、printステートメントとyieldステートメントは異なります。これを試して:

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]]

コピーを作成する代わりに同じリストを回しているので、最後の利回りがあなたの答えであることがわかります。

于 2009-05-12T01:19:19.480 に答える