Ketika Anda menulis, [x]*3
Anda mendapatkan, pada dasarnya, daftar [x, x, x]
. Yaitu, daftar dengan 3 referensi yang sama x
. Ketika Anda memodifikasi single ini, x
itu terlihat melalui ketiga referensi untuk itu:
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]]
Untuk memperbaikinya, Anda perlu memastikan bahwa Anda membuat daftar baru di setiap posisi. Salah satu cara untuk melakukannya adalah
[[1]*4 for _ in range(3)]
yang akan mengevaluasi ulang [1]*4
setiap kali alih-alih mengevaluasi satu kali dan membuat 3 referensi ke 1 daftar.
Anda mungkin bertanya-tanya mengapa *
tidak dapat membuat objek independen seperti pemahaman daftar. Itu karena operator perkalian *
beroperasi pada objek, tanpa melihat ekspresi. Saat Anda menggunakan *
untuk mengalikan [[1] * 4]
dengan 3, *
hanya melihat daftar 1-elemen yang [[1] * 4]
dievaluasi, bukan [[1] * 4
teks ekspresi. *
tidak tahu bagaimana membuat salinan elemen itu, tidak tahu bagaimana cara mengevaluasi kembali [[1] * 4]
, dan tidak tahu Anda bahkan ingin salinan, dan secara umum, bahkan mungkin tidak ada cara untuk menyalin elemen.
Satu-satunya pilihan *
adalah membuat referensi baru ke sublist yang ada alih-alih mencoba membuat sublists baru. Hal lain akan menjadi tidak konsisten atau memerlukan pendesainan ulang besar terhadap keputusan desain bahasa mendasar.
Sebaliknya, pemahaman daftar mengevaluasi kembali ekspresi elemen pada setiap iterasi. [[1] * 4 for n in range(3)]
Mengevaluasi kembali [1] * 4
setiap waktu karena alasan yang sama [x**2 for x in range(3)]
mengevaluasi kembali x**2
setiap waktu. Setiap evaluasi [1] * 4
menghasilkan daftar baru, sehingga pemahaman daftar melakukan apa yang Anda inginkan.
Kebetulan, [1] * 4
juga tidak menyalin elemen [1]
, tapi itu tidak masalah, karena bilangan bulat tidak dapat diubah. Anda tidak dapat melakukan sesuatu seperti 1.value = 2
dan mengubah angka 1 menjadi angka 2.
[x]*3
menyimpan 3 referensi suka[x, x, x]
hanya benar bilax
bisa berubah. Ini tidak berfungsi untuk misalnyaa=[4]*3
, di mana setelaha[0]=5
,a=[5,4,4].