Ketika Anda menulis, [x]*3Anda mendapatkan, pada dasarnya, daftar [x, x, x]. Yaitu, daftar dengan 3 referensi yang sama x. Ketika Anda memodifikasi single ini, xitu 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]*4setiap 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] * 4teks 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] * 4setiap waktu karena alasan yang sama [x**2 for x in range(3)]mengevaluasi kembali x**2setiap waktu. Setiap evaluasi [1] * 4menghasilkan daftar baru, sehingga pemahaman daftar melakukan apa yang Anda inginkan.
Kebetulan, [1] * 4juga tidak menyalin elemen [1], tapi itu tidak masalah, karena bilangan bulat tidak dapat diubah. Anda tidak dapat melakukan sesuatu seperti 1.value = 2dan mengubah angka 1 menjadi angka 2.
[x]*3menyimpan 3 referensi suka[x, x, x]hanya benar bilaxbisa berubah. Ini tidak berfungsi untuk misalnyaa=[4]*3, di mana setelaha[0]=5,a=[5,4,4].