1

この問題は非常に簡単に理解できます。プログラムは次のとおりです。

hisc = [1,2,3,4]
print("\n", hisc)

ohisc = hisc
hisc.append(5)

print("\nPreviously...", ohisc)
print("\nAnd now...", hisc)
input("\nETE")

実行すると、ohiscは5を取得します。なぜohiscが変わるのですか?どうすれば変更を防ぐことができますか?これが明らかなことである場合はお詫び申し上げます。

4

3 に答える 3

5

Python変数は参照です。そのため、割り当ては変数の内容ではなく参照をコピーします。

これを回避するには、新しいオブジェクトを作成するだけです。

ohisc = list(hisc)

これは、指定されたiterableから新しいリストを作成するlistコンストラクターを使用しています。

または、スライス(新しいオブジェクトを作成する)から割り当てることもできます。

ohisc = hisc[:]

[]特定のコレクションからサブセットを抽出するために使用される一般的なスライス演算子です。開始位置と終了位置を省略します(デフォルトでは、それぞれコレクションの開始位置と終了位置になります)。

于 2013-03-14T19:53:07.080 に答える
2

コンラッド・ルドルフの答えのすべてを確実に理解する必要があります。そして、私はあなたの特定のケースでは、それもあなたが望むものだと思います。しかし、多くの場合、より良い方法があります。オブジェクトの変更(つまり、オブジェクトをインプレースで変更する)を回避する場合、2つの名前が同じオブジェクトを参照しているかどうかは重要ではありません。たとえば、次のように変更できます。

hisc.append(5)

これに:

hisc = hisc + [5]

それはその場で変わりませんhisc。の末尾にが追加された新しいを作成し、listそれ5をに割り当てhiscます。したがって、同じものを指していたという事実はohisc重要ではありません。それは、指し示すために、変更されずにまだそこにあります。listhisclistohisc

リストのすべての負の値を0に置き換えたいとしましょう。これは、ミューテーションを使用すると非常に簡単です。

for i in range(len(lst)):
    list[i] = max(list[i], 0)

しかし、なしでさらに簡単に:

lst = [max(elem, 0) for elem in lst]

では、すべてのネガティブリスト要素を削除したい場合はどうでしょうか。シーケンスのループ中にシーケンスの形状を変更することはできないため、リストのコピーを作成するか(一方のコピーをループしてもう一方のコピーを変更できるようにする)、またはより複雑なアルゴリズムを考え出す必要があります(たとえば、各0を逆方向に交換してから、最後にあるすべての0を削除します)。しかし、不変に行うのは簡単です。

lst = [elem for elem in lst if elem >= 0]

それで、いつあなたは突然変異したいと思うでしょうか?多くの場合、同じオブジェクトへの2つの参照が必要になるため、一方を更新すると、もう一方に変更が表示されます。その場合、他の人が見るには明らかに実際の変更が必要です。

于 2013-03-14T21:00:50.050 に答える
1

何が起こっているのかについての良い説明は次のとおりです。Python:リストを正しい方法でコピーする

基本的に、あなたはリストへのポインタを作成していますが、あなたがしたいのはリストのコピーを作成することです。

代わりにこれを試してください:

hisc = [1,2,3,4]
ohisc = hisc[:]
于 2013-03-14T20:04:06.043 に答える