使用=[]与.clear()清空列表的行为差异及问题原因分析
问题:openpyxl转换嵌套列表时clear()与重新赋值的差异?
原始Excel数据
key Book Author Price 1 Flowers Peter 11 2 Animals Paul 12 3 Trees Mary 13 4 Cars Otto 14
测试代码
import openpyxl as xls rowList = [] comList = [] wb = xls.load_workbook('ExampleExcel.xlsx') ws = wb.active srow: int = ws.max_row scol: int = ws.max_column for x in range(1, srow+1): rowList.clear() # 可行的替代写法 rowList = [] for y in range(1, scol+1): rowList.append(ws.cell(row=x, column=y).value) comList.append(rowList) print(comList )
两种执行结果
- 使用
rowList = []时(预期结果):
[['key', 'Book', 'Author', 'Price'], [1, 'Flowers', 'Peter', 11], [2, 'Animals', 'Paul', 12], [3, 'Trees', 'Mary', 13], [4, 'Cars', 'Otto', 14]]
- 使用
rowList.clear()时(异常结果):
[[4, 'Cars', 'Otto', 14], [4, 'Cars', 'Otto', 14], [4, 'Cars', 'Otto', 14], [4, 'Cars', 'Otto', 14], [4, 'Cars', 'Otto', 14]]
原因分析
核心差异在于列表对象的引用机制:
rowList = []:每次循环都会创建一个全新的列表对象,然后把这个新对象的引用添加到comList中。comList里的每个元素都是独立的列表,各自存储对应行的数据,互不干扰。rowList.clear():只是清空了原有列表里的内容,但列表本身的引用地址没有变。每次循环都是往同一个列表对象里填充新行的数据,然后把这个相同的引用重复添加到comList中。最终comList里的所有元素其实都指向同一个列表对象,所以打印时显示的都是最后一次循环填充的内容。
举个极简例子验证这个逻辑:
a = [] b = [] a.append(1) b.append(a) # b现在是[[1]] a.clear() a.append(2) b.append(a) # b现在是[[2], [2]],因为两个元素都指向同一个a print(b)
内容的提问来源于stack exchange,提问作者Martin
相关产品推荐
相关产品推荐

