5

私はPythonを学んでいて、dequeを作ろうとしています。ただし、間違った出力が得られ、その理由がわかりません。私のコードは次のとおりです。

p = [2, 1], [1, 1]
init_q= deque()

init_q.append(p)
for i in range(len(p)):
    for j in range(len(p[i])):
        temp = p[i][j]
        p[i][j] = 0
        init_q.append(p)
        p[i][j] = temp

while init_q:
    print init_q.pop()

リストを取得するこのコードでは、5 つのリストを持つキューを作成します。そのうちの 4 つのリストには異なる場所で 0 が含まれています。必要な結果は次のとおりです。

([2, 1], [1, 1])
([0, 1], [1, 1])
([2, 0], [1, 1])
([2, 1], [0, 1])
([2, 1], [1, 0])

しかし、私が得る結果は次のとおりです。

([2, 1], [1, 1])
([2, 1], [1, 1])
([2, 1], [1, 1])
([2, 1], [1, 1])
([2, 1], [1, 1])
4

3 に答える 3

4

オブジェクトを両端キューに入れてから、オブジェクトを変更しています。実際、常に同じオブジェクトを両端キューに入れるので、両端キューには 1 つのオブジェクト p への参照しかありません。

于 2013-01-07T03:29:23.133 に答える
3

コードを単純化して、Python Tutorで視覚化を作成しました。いじってみると、何が起こっているのかを簡単に確認できます。

コードを 1 行変更するだけで、これを修正できます。

init_q.append(map(list, p))    # Initialize a new list from p's element lists

上記の変更を使用した視覚化は次のとおりです。

于 2013-01-07T06:59:15.273 に答える
1

Ned Batchelder の回答に対する私のコメントをフォローアップすると、同じことを不変に行う方法が次のようになります。

for i in range(len(p)):
    for j in range(len(p[i])):
        temprow = [0 if y==j else p[i][y] for y in range(len(p[i]))]
        temp = [temprow if x==i else p[x] for x in range(len(p))]
        init_q.append(temp)

この場合、結果は彼の提案よりもはるかに読みにくいと思います。

        temp = copy.deepcopy(p)
        temp[i][j] = 0
        init_q.append(temp)

私が言ったように、物事が単純になることもあれば、単純でなくなることもあります. list内の複数の 、init_qまたはさらに悪いことに、listそれらlistの内のサブが ID を共有しているかどうかを心配する必要はありません。

トレードオフが価値があるかどうかは、実際にはケースバイケースの決定であり、おそらくプログラマーごとに異なります。この場合、私は不変の解決策を使用しませんし、他の多くの (Python) プログラマーが使用するとは思えません。しかし、それを書く方法を知ることは価値があります。

これを 2D リストの両端キューではなく 3D リストとして記述し、deque. 明らかに同等ですが、概念的には次のように考える方が簡単かもしれません。

init_q.append(p)
q = [copy.deepcopy(p) for i in range(len(p)) for j in range(len(p[i]))]
for i in range(len(p)):
    for j in range(len(p[i])):
        q[i*len(p[i])+j][i][j] = 0
init_q.extend(q)

PS、この種のことをたくさん行っている場合は、 をご覧になることをお勧めしますnumpy。これがあなたの問題全体である場合、それはあなたにとって何の役にも立たないでしょう…しかし、多次元配列でもっと複雑なことをするなら、それはうまくいくでしょう。

于 2013-01-07T04:50:46.577 に答える