Kiedy piszesz [x]*3
, dostajesz w zasadzie listę [x, x, x]
. To znaczy lista z 3 odniesieniami do tego samego x
. Kiedy następnie zmodyfikujesz ten singiel, x
będzie on widoczny poprzez wszystkie trzy odniesienia do niego:
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]]
Aby to naprawić, musisz utworzyć nową listę w każdej pozycji. Jednym ze sposobów na to jest
[[1]*4 for _ in range(3)]
który za [1]*4
każdym razem będzie ponownie oceniać, zamiast oceniać go raz i czyniąc 3 odniesienia do 1 listy.
Możesz się zastanawiać, dlaczego *
nie można tworzyć niezależnych obiektów w taki sposób, jak robi to lista. Jest tak, ponieważ operator mnożenia *
działa na obiektach, nie widząc wyrażeń. Kiedy używasz *
do pomnożenia [[1] * 4]
przez 3, *
widzi tylko listę 1-elementową [[1] * 4]
, a nie [[1] * 4
tekst wyrażenia. *
nie ma pojęcia, jak wykonać kopię tego elementu, nie ma pojęcia, jak dokonać ponownej oceny [[1] * 4]
, i nie ma pojęcia, że chcesz kopii, a ogólnie rzecz biorąc, może nie być nawet sposobu na skopiowanie elementu.
Jedyną opcją *
jest tworzenie nowych odniesień do istniejącej listy podrzędnej zamiast prób tworzenia nowych list podrzędnych. Wszystko inne byłoby niespójne lub wymagałoby poważnego przeprojektowania podstawowych decyzji dotyczących projektowania języka.
W przeciwieństwie do tego, zrozumienie listy ponownie ocenia wyrażenie elementu przy każdej iteracji. [[1] * 4 for n in range(3)]
ponownej waloryzacji [1] * 4
za każdym razem z tego samego powodu [x**2 for x in range(3)]
ponownej waloryzacji x**2
za każdym razem. Każda ocena [1] * 4
generuje nową listę, więc zrozumienie listy robi to, co chciałeś.
Nawiasem mówiąc, [1] * 4
również nie kopiuje elementów [1]
, ale to nie ma znaczenia, ponieważ liczby całkowite są niezmienne. Nie możesz zrobić czegoś takiego 1.value = 2
i zmienić 1 w 2.
[x]*3
przechowuj 3 odnośniki, tak jak[x, x, x]
jest właściwe tylko wtedy, gdyx
można je modyfikować. To dzieło nie podlega na przykłada=[4]*3
, gdzie poa[0]=5
,a=[5,4,4].