11

「Python プログラミング」の入門書であるHow to think like a computer scientistを読んでいます。

*リストに適用されたときの乗算演算子 ( ) の動作を明確にしたいと思います。

関数make_matrixを考えてみましょう

def make_matrix(rows, columns):
"""
  >>> make_matrix(4, 2)
  [[0, 0], [0, 0], [0, 0], [0, 0]]
  >>> m = make_matrix(4, 2)
  >>> m[1][1] = 7
  >>> m
  [[0, 0], [0, 7], [0, 0], [0, 0]]
"""
return [[0] * columns] * rows

実際の出力は

[[0, 7], [0, 7], [0, 7], [0, 7]]

make_matrixの正しいバージョンは次のとおり です。

def make_matrix(rows, columns):
"""
  >>> make_matrix(3, 5)
  [[0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0]]
  >>> make_matrix(4, 2)
  [[0, 0], [0, 0], [0, 0], [0, 0]]
  >>> m = make_matrix(4, 2)
  >>> m[1][1] = 7
  >>> m
  [[0, 0], [0, 7], [0, 0], [0, 0]]
"""
matrix = []
for row in range(rows):
    matrix += [[0] * columns]
return matrix

make_matrixの最初のバージョンが失敗する理由(本の 9.8 で説明されているように) は、

...各行は他の行のエイリアスです...

なぜだろう

[[0] * columns] * rows

原因...各行は他の行のエイリアスです...

だがしかし

[[0] * columns]

つまり、行のそれぞれ[0]が他の行要素のエイリアスではない理由です。

4

2 に答える 2

20

Python のすべてはオブジェクトであり、明示的に要求されない限り、Python は決してコピーを作成しません。

あなたがするとき

innerList = [0] * 10

10 個の要素を持つリストを作成し、それらすべてが同じintオブジェクト0を参照しているとします。

整数オブジェクトはimmutableであるため、そうすると

innerList[1] = 15

別の整数を参照するように、リストの 2 番目の要素を変更しています15intオブジェクトの不変性により、これは常に機能します。

それが理由です

outerList = innerList * 5

list5 つの要素を持つオブジェクトを作成します。各要素は上記と同じものへのinnerList参照です。しかし、listオブジェクトは可変であるため:

outerList[2].append('something')

以下と同じです:

innerList.append('something')

これらは同じlistオブジェクトへの 2 つの参照であるためです。したがって、要素はその単一の になりlistます。重複しているように見えますが、実際にはlistオブジェクトが 1 つしかなく、それへの参照が多数あります。

対照的に、

outerList[1] = outerList[1] + ['something']

ここでは、別のオブジェクトを作成 listし ( +with リストの使用は明示的なコピーです)、そのオブジェクトへの参照を の 2 番目の位置に割り当てていますouterList。このように要素を「追加」しても (実際には追加ではなく、別のリストを作成します)、innerList影響を受けません。

于 2009-06-10T11:27:19.793 に答える
-4

リストはプリミティブではなく、参照によって渡されます。リストのコピーは、リストへのポインターです (C 用語で)。浅いコピーを行わない限り、リストに対して行うことはすべて、リストのすべてのコピーとその内容のコピーに適用されます。

[[0] * columns] * rows

おっと、[0] へのポインターの大きなリストを作成しました。1 つを変更すると、それらすべてが変更されます。

整数は参照渡しではなく、実際にコピーされるため、 [0] * コンテンツは実際には多くの新しい 0 を作成し、それらをリストに追加しています。

于 2009-06-10T11:11:43.663 に答える