Python二维列表赋值读取异常及两种赋值方式差异咨询
为什么两次列表赋值结果差异这么大?
嘿,这个问题其实是Python列表创建和赋值的经典坑,我来给你拆解明白:
第一个代码的问题根源:共享引用的“浅拷贝”坑
先看你写的第一段代码:
a = [[0]*3]*4 for i in range(4): for j in range(3): a[i][j] = i+j print(a[i][j]) print(a)
这里的关键是[[0]*3]*4到底创建了什么:
[0]*3确实创建了一个包含3个0的独立列表,咱们暂时叫它sub_list;- 但
*4并没有创建4个新的sub_list,而是把同一个sub_list的引用重复了4次放到了外层列表a里。
换句话说,a[0]、a[1]、a[2]、a[3]其实都是指向内存中同一个列表对象的“钥匙”。当你在循环里执行a[i][j] = i+j时,你并不是在修改第i个独立子列表的第j个元素,而是在修改那个唯一的sub_list的第j个元素。
循环里每次打印a[i][j]时,你刚修改完这个共享列表的对应位置,所以看起来是对的;但当循环结束打印整个a时,四个子列表其实都是那个被反复修改后的共享列表,自然内容完全相同。
第二个代码为什么能正常工作?
再看第二段代码:
a = [[0]*3]*4 for i in range(4): a[i] = [i, 2*i, 3*i]
这里的核心区别是赋值操作的对象变了:
- 原来的
a[i]是指向共享子列表的“钥匙”,但现在你执行a[i] = [i, 2*i, 3*i],相当于直接给a[i]换了一把开新房子的钥匙——也就是创建了一个全新的列表对象,把a的第i个位置的引用从原来的共享子列表替换成这个新列表。
到循环结束时,a里的四个元素都是各自独立的新列表,没有共享引用的问题,所以结果符合预期。
额外补充:如何正确创建独立子列表的二维列表?
如果想避免第一个代码的坑,正确创建4个独立的3元素列表,应该用列表推导式:
a = [[0]*3 for _ in range(4)]
这里的for _ in range(4)会循环4次,每次都创建一个新的[0]*3列表,这样每个子列表都是独立的,修改时就不会互相影响了。
内容的提问来源于stack exchange,提问作者haik
相关产品推荐
相关产品推荐

