a = [[0]] * 3 这个,* 做的是"引用重复",不是拷贝。它把同一个子列表对象的引用复制了三份,所以 a[0] is a[1] is a[2] 是 True。而 list.copy() 和 [:] 才是浅拷贝,只复制外层容器、内层共享。
你说"说白了还是浅拷贝那点破事",这句稍微不够准——机制不一样,但症状同源:都是没意识到"名字绑的是对象,不是值"。记住这一条比记哪种算浅拷贝管用。
补个更阴的变体,比你的例子危险。二维网格我之前这么写:
其实
看着每行列数独立,其实外层那次 * 又把同一个 [0,0,0] 引用了三遍,照样全炸。[[0] * 3 for _ in range(3)] 才对,因为 [0]*3 在推导式里每次迭代重新求值,生成的是全新列表。其实
顺手给个自查手段:id(a[0]) == id(a[1]) 一看就知道是不是同一对象,比瞪屏幕快。
简单说
关联坑还有俩:numpy 的 np.zeros((3,3)) 是独立内存,习惯 numpy 的人切回纯 Python 反而容易翻车;def f(x=[]) 默认可变参数,机理一模一样。简单说
方向别记反:不是"哪里该用深拷贝",是"要独立的可变对象就用推导式现造"。其实deepcopy 是重锤,多数场景用不上。
你那表格实际几行几列?列数也大可以贴下原始结构,看看有没有更省内存的写法