Python3中存储列表迭代结果出现非预期结果的问题咨询
问题原因说明
核心本质
Python 中列表属于可变引用类型,fl.append(l) 操作并不会把当前时刻的列表值拷贝存入fl,而是将原列表l的**内存引用(也就是指向原列表对象的指针)**追加到fl中。fl里的所有元素都指向同一个内存地址,也就是最初创建的那个l列表对象,后续对这个对象的所有修改,都会同步影响fl里所有存储该引用的位置。
执行流程逐行拆解
整个循环的实际执行逻辑可以拆成4步:
- 初始状态:创建列表对象
["A", "B", "C"],变量l指向这个对象的内存地址,fl为空列表 - 第1次循环:对原列表执行
pop(0)+append操作,原列表对象被修改为['B', 'C', 'A'],此时执行fl.append(l),把这个列表的内存地址存入fl[0] - 第2次循环:继续修改同一个原列表对象,把它改为
['C', 'A', 'B'],执行fl.append(l)后,fl[1]和fl[0]指向完全相同的列表对象——此时这个对象已经被修改为['C', 'A', 'B'],所以fl[0]的取值也会同步变成这个值 - 第3次循环:再次修改同一个原列表对象,把它改回
['A', 'B', 'C'],执行fl.append(l)后,fl[2]也指向这个内存地址
最终打印fl时,三个存储的引用都指向最终状态的同一个列表对象,所以输出全是['A', 'B', 'C']
为什么直接调用print(l)输出正常?
print(l)是读取当前时刻列表的实时值,每次循环执行到print语句时,列表正好处于本次迭代修改后的状态,所以能输出符合预期的中间结果。
解决方法
每次往fl存储的时候,手动生成当前列表的值副本(也就是在内存中新建一个和当前列表内容完全一致的独立对象),再追加进去即可,常见实现方式有三种:
fl.append(l.copy())fl.append(l[:])(利用列表全量切片生成副本)fl.append(list(l))(通过列表构造函数生成新对象)
修改后执行代码,就能得到预期的输出:
[['B', 'C', 'A'], ['C', 'A', 'B'], ['A', 'B', 'C']]
内容的提问来源于stack exchange,提问作者RandallShanePhD
相关产品推荐
相关产品推荐

