Wenn Sie schreiben, erhalten [x]*3
Sie im Wesentlichen die Liste [x, x, x]
. Das heißt, eine Liste mit 3 Verweisen darauf x
. Wenn Sie diese Single dann ändern x
, ist sie über alle drei Verweise darauf sichtbar:
x = [1] * 4
l = [x] * 3
print(f"id(x): {id(x)}")
# id(x): 140560897920048
print(
f"id(l[0]): {id(l[0])}\n"
f"id(l[1]): {id(l[1])}\n"
f"id(l[2]): {id(l[2])}"
)
# id(l[0]): 140560897920048
# id(l[1]): 140560897920048
# id(l[2]): 140560897920048
x[0] = 42
print(f"x: {x}")
# x: [42, 1, 1, 1]
print(f"l: {l}")
# l: [[42, 1, 1, 1], [42, 1, 1, 1], [42, 1, 1, 1]]
Um dies zu beheben, müssen Sie sicherstellen, dass Sie an jeder Position eine neue Liste erstellen. Ein Weg, dies zu tun, ist
[[1]*4 for _ in range(3)]
Dies wird [1]*4
jedes Mal neu bewertet, anstatt es einmal zu bewerten und 3 Verweise auf 1 Liste zu machen.
Sie fragen sich vielleicht, warum *
unabhängige Objekte nicht so erstellt werden können wie das Listenverständnis. Dies liegt daran, dass der Multiplikationsoperator *
Objekte bearbeitet, ohne Ausdrücke zu sehen. Wenn Sie mit 3 *
multiplizieren [[1] * 4]
, wird *
nur die 1-Element-Liste [[1] * 4]
ausgewertet, nicht der [[1] * 4
Ausdruckstext. *
hat keine Ahnung, wie Kopien dieses Elements erstellt werden sollen, keine Ahnung, wie eine Neubewertung vorgenommen werden soll [[1] * 4]
, und keine Ahnung, dass Sie überhaupt Kopien wünschen, und im Allgemeinen gibt es möglicherweise nicht einmal eine Möglichkeit, das Element zu kopieren.
Die einzige Möglichkeit *
besteht darin, neue Verweise auf die vorhandene Unterliste zu erstellen, anstatt zu versuchen, neue Unterlisten zu erstellen. Alles andere wäre inkonsistent oder würde eine umfassende Neugestaltung grundlegender Entscheidungen zum Sprachdesign erfordern.
Im Gegensatz dazu bewertet ein Listenverständnis den Elementausdruck bei jeder Iteration neu. [[1] * 4 for n in range(3)]
wird [1] * 4
jedes Mal aus demselben Grund [x**2 for x in range(3)]
neu bewertet, x**2
jedes Mal neu bewertet . Jede Auswertung von [1] * 4
generiert eine neue Liste, sodass das Listenverständnis das tut, was Sie wollten.
Kopiert übrigens [1] * 4
auch nicht die Elemente von [1]
, aber das spielt keine Rolle, da Ganzzahlen unveränderlich sind. Sie können so etwas nicht tun 1.value = 2
und eine 1 in eine 2 verwandeln.
[x]*3
3 Referenzen speichern wie[x, x, x]
ist nur dann richtig, wennx
es veränderlich ist. Dies funktioniert nicht für zBa=[4]*3
, wo nacha[0]=5
,a=[5,4,4].