2

リスト割り当ての仕組みを理解するための簡単な演習を行っていました。リスト L1 を L2 に割り当ててから、要素を L1 に追加すると、L1 と L2 の両方が変更されます。ただし、リスト L3 を L2 のサブスライスに割り当ててから、要素を L3 に追加すると、L3 の変更は L2 から切断されます。これはどのように達成されますか?L3 は実際には、リストのサブスライスを含む別の場所を指していますが、L1 と L2 は同じ場所を指しています。そうですか?

>>> L1 = []
>>> L2 =[1,2,3]
>>> L1 = L2
>>> L1.append(4)
>>> L1
[1, 2, 3, 4]
>>> L2
[1, 2, 3, 4]
>>> L3 =L2[:2]
>>> L3
[1, 2]
>>> L3.append(5)
>>> L3
[1, 2, 5]
>>> L2
[1, 2, 3, 4]
4

3 に答える 3

3

答えは簡単です。代入は参照を代入します。そのため、 への変更L1が に表示されL2ます。それらは同じオブジェクトです。

ただし、スライスは範囲の (浅い)コピーを作成します。したがって、 への変更L3は から切断されL2ます。

実際、シーケンスのコピーを作成するには、直接代入を使用できないため、代わりにスライスを使用できます。

>>> L4 = L2[:]
>>> L4.append(5)
>>> L2
[1, 2, 3, 4]

…しかし、それはより一般的にコンストラクターを介して行われL4 = list(L2)ます。

于 2013-07-21T23:28:55.167 に答える
0

上記の答えに加えて、整数や文字列ではなく、変更可能なオブジェクトのリストがある場合、コピーの性質が重要になります。リストの要素は、スライスしても同じオブジェクトを指しています。

>>> a = { 'a': 0 }
>>> b = { 'b' : 0 }
>>> c = { 'c' : 0 }
>>> l = [ a, b, c ]
>>> m = l[ : 2] 

mlには、同じものへの参照が含まれています。

>>> m
[{'a': 0}, {'b': 0}]
>>> m[0]['a'] = 1
>>> m
[{'a': 1}, {'b': 0}]
>>> l
[{'a': 1}, {'b': 0}, {'c': 0}]

ただし、mlは別のものです。

>>> m[0] = {'d': 1}
>>> m
[{'d': 1}, {'b': 0}]
>>> l
[{'a': 1}, {'b': 0}, {'c': 0}] 
于 2013-07-22T01:22:24.587 に答える
0

(私は例であまりにも多くの時間を無駄にし、@Konrad Rudolph が私を答えに打ち負かしました。私は基本的に彼と同じことを言っています)

Python は内部で C ポインターの割り当てと同等の処理を行っており、L1 はメモリ内のリストのアドレスを保持し、L2 は同じアドレスをコピーしただけです。

is演算子を使用するだけで、コードをチェックインできます。

>>> L1 is L2
True

ただし、スライスを使用する場合は、元のリストとは異なるため、新しいリストを作成する必要がありますが、すべてをコピーするのではなく、内部のオブジェクトへの参照をコピーするだけです。

より複雑な例を次に示します。

>>> L1 = [1, [2, 3], 4]
>>> L2 = L1
>>> L2
[1, [2, 3], 4]
>>> L1[1] is L2[1]
True

わかりましたので、L1内部にリストを含むリストを保持します。これを辞書、文字列、またはその他の python オブジェクトに置き換えることができます。リスト内のリストに対してis演算子が返されることに注意してください。True

次に、スライスのトリックを行う場合:

>>> L3 = L1[:2]
>>> L3
[1, [2, 3]]
>>> L3 is L1
False
>>> L3[1] is L2[1]
True

外部リストは変更されていますが、内部のオブジェクトは同じままです。これは、浅いコピーとして知られています。実際、リスト内のリストに新しいアイテムを追加する場合、同じルールが引き続き適用されます。

>>> L3[1].append(9)
>>> L3
[1, [2, 3, 9]]
>>> L1
[1, [2, 3, 9], 4]

(追加された 9 に注意してください) と の両方の内部のリストL1L3変更されています。

対照的に、deepcopy浅いコピーが望ましくない場合に行うことができます。

>>> from copy import deepcopy
>>> L3 = deepcopy(L1)
>>> L3
[1, [2, 3, 9], 4]
>>> L3 is L1
False
于 2013-07-22T02:25:17.357 に答える