Εσύ έχεις δίκιο πολύ, αλλά εχω και εγώ λίγο γιατί δεν ήξερα...
Κοίταξε τι έκανα εγώ χτες:
>>> a = [[1,2],[3,4]]
>>> b = [[7,8],[9,0]]
>>> id(a[0][0]) == id(b[0][0]) # Check if a[0][0] "points" to b[0][0]
False # It doesn't
>>> a[0][0] = b[0][0]
>>> id(a[0][0]) == id(b[0][0]) # Check if a[0][0] "points" to b[0][0]
True # It does
>>> a
[[7, 2], [3, 4]]
>>> b
[[7, 8], [9, 0]]
>>> a[0][0] = b[0][0] * 2
>>> id(a[0][0]) == id(b[0][0])
False
>>> a
[[14, 2], [3, 4]]
>>> b
[[7, 8], [9, 0]]
όπως βλέπεις η τιμή της "b" δεν άλλαξε.
Η διαφορά με αυτό που έκανες εσύ ήταν ότι δεν αντέγραψα τη λίστα "a" με τη "list()" αλλά δημιούργησα μια καινούρια. Κοίτα ποια είναι η διαφορά:
>>> a = [[1,2],[3,4]]
>>> b = list(a)
>>> id(a) == id(b)
False # As expected! But...
>>> id(a[0][0]) == id(b[0][0])
True # Each element of b "points" at the same object as a!!!
Κάτι μάθαμε και σήμερα...
Λογικά στην αντιγραφή με list, η σειρα είναι η εξής:
1. Υπολογίζεται το δεξί τμήμα της εκχώρησης τιμής "b[0][0] * 2"
2. Εκχωρείται στο αριστερό, δηλαδή στο "a[0][0]"
3. To "b[0][0]" επειδή δείχνει στο ίδιο αντικείμενο με το "a[0][0]", δείχνει και αυτό τη νέα τιμή.
Αν κάποιος το καταλαβαίνει καλύτερα ας μας το εξηγήσει.