Python [[0]*3]*3初始化二维数组 赋值对角线时全元素被修改问题
问题根因
使用[[0]*3]*3创建二维列表时,外层列表包含的3个元素是同一个内层列表的引用,而非3个独立的列表对象。
- 对不可变类型(比如整数)做乘法复制时不会出现引用问题,因此
[0]*3生成的单维列表是正常的,包含3个独立的0值。 - 但对列表这种可变类型做乘法复制时,复制的是对象引用而非对象本身,因此
[list_obj]*3得到的三个元素都指向同一块内存地址的同一个列表。 - 原代码循环赋值对角线时,三次操作本质是修改同一个公共列表的0、1、2号索引位置,最终这个公共列表的三个位置都被赋值为1,外层列表因为三个元素都指向它,就呈现出所有元素全为1的异常结果。
问题复现
a = [[0]*3]*3 print("INIT ARRAY: ", a) for i in range(3): a[i][i] = 1 print("FINAL ARRAY:", a)
运行输出:
INIT ARRAY: [[0, 0, 0], [0, 0, 0], [0, 0, 0]] FINAL ARRAY: [[1, 1, 1], [1, 1, 1], [1, 1, 1]]
可以通过打印对象id验证引用关系:
a = [[0]*3]*3 # 三个内层列表的内存地址完全一致,证明是同一个对象 print(id(a[0]), id(a[1]), id(a[2]))
正确实现方式
不要嵌套使用列表乘法创建多维列表,改用列表推导式,每次迭代生成全新的独立内层列表即可:
a = [[0]*3 for _ in range(3)] print("INIT ARRAY: ", a) for i in range(3): a[i][i] = 1 print("FINAL ARRAY:", a)
运行输出符合预期:
INIT ARRAY: [[0, 0, 0], [0, 0, 0], [0, 0, 0]] FINAL ARRAY: [[1, 0, 0], [0, 1, 0], [0, 0, 1]]
内容的提问来源于stack exchange,提问作者Krishna Sai Tarun
相关产品推荐
相关产品推荐

