2

ここの奇妙な問題、6 行目と 11 行目、奇妙な問題です。理由がわかりません。

1 l1 = ['a', 'b', 'c']
2 
3 l2 = [[]] * 3
4 for i in xrange(0, len(l1)):
5     l2[i%len(l1)].extend(l1[i]) # look! not [li[i]] here
6 print 'l2: ', l2  # problem is here
7 
8 l3 = [[]] * 3
9 for i in xrange(0, len(l1)):
10     l3[i%len(l1)].extend([l1[i]]) 
11 print 'l3: ', l3
12 
13 l4 = [[]] * 3
14 for i in xrange(0, len(l1)):
15     if l4[i%len(l1)] == []:
16         l4[i%len(l1)] = [l1[i]]
17     else:
18         l4[i%len(l1)].extend([l1[i]])
19 print 'l4: ', l4

アウトプットブロー:

l2:  [['a', 'b', 'c'], ['a', 'b', 'c'], ['a', 'b', 'c']]
l3:  [['a', 'b', 'c'], ['a', 'b', 'c'], ['a', 'b', 'c']]
l4:  [['a'], ['b'], ['c']]

誰かが理由を指摘できますか?ありがとう。

4

3 に答える 3

4

リストを int で乗算すると、深いコピーではなく、浅いコピーが作成されるためです。

Python は、明示的にそうするように指示しない限り、ほとんどのものに対してディープ コピーを作成しません。これは、ディープ コピーがオブジェクトを処理する方法により、オブジェクトが過剰にコピーしたり、自己参照に問題が発生したりする可能性があるためです。

Python にはdeepcopyでそれを処理する方法がありますが、ユーザー定義クラスの場合は、そのメソッドを自分で実装する必要があります。すべての問題を回避するために、変更可能なオブジェクト (リストなど) を例のように暗黙的にコピーすると、浅いコピーが作成されます。

于 2013-09-06T02:40:06.600 に答える
2

文字列も一連の文字であるため、5 行目は 10 行目と同じように機能します。たとえば、次のようになります。

list('abc') == ['a', 'b', 'c']
list('a')   == ['a']

この場合、.extend('a')文字列'a'が 1 文字のシーケンスと見なされるため、これも機能'a'します。しかし、比較.extend('abc').extend(['abc'])て、それらが同一ではないことを確認してください。(最初のものは少し予想外の結果になるので、使用はお勧めしません。)

于 2013-09-06T10:29:25.953 に答える
0

あなたが期待していること、そして中級から経験豊富なプログラマーがまだ時々落ちる可能性があるのは、

l = [some_object] * 3

のコピーを作成しsome_objectます。ただし、Python では、これはそのオブジェクトへの参照を複製するだけなので、実際には同じオブジェクトが 1 つのリストに 3 回含まれています。リストは変更可能であるため、1 つの参照を介してオブジェクトを変更すると、他の参照を介して表示される内容も変更されます。

コメントで既に述べたように、別のオブジェクトを作成する場合は、次のようにする必要があります。

[create_some_object for _ in range(3)]

リストの場合、それは簡単です: [ [] for _ in range(3)].

タプル、文字列、整数、NoneType などの不変オブジェクトを扱う場合など、場合によっては違いに気付かないことがあります。これらは変更できず、置き換えられるだけです。したがって、1 つのオブジェクトへの参照がいくつ存在してもかまいません。なぜなら、ある場所でオブジェクトを変更したい場合は、新しいオブジェクトを再構築してその参照を置き換える必要があるからです。他の参照は同じオブジェクトを指し続けるため、変更されません。

于 2013-09-06T13:07:07.353 に答える