Python拆分列表到预定义子列表时首元素异常为0的问题排查
问题根因
bug出在你内层循环的错误写法:for num[Cnt] in num:
Python的for 变量 in 可迭代对象语法,每轮迭代的第一步是把可迭代对象当前遍历到的值赋值给你声明的这个循环变量。你没有用独立的临时变量承接循环值,反而把循环变量指向了原列表num的Cnt索引位置,直接导致原列表被意外篡改:
- 处理第一个子列表
list1时,初始Cnt=0,for循环第一次迭代就把num[0]的值0赋值给num[0],看起来没变化,后续while逻辑正常取数填充到长度8,此时Cnt累加到8 - 处理第二个子列表
list2时,for循环启动的第一次迭代,直接把当前遍历到的num[0](也就是0)赋值给num[Cnt]即num[8],原本存在num[8]的8被覆盖成0,后续while从Cnt=8开始取数,第一个取到的就是被篡改后的0,填充到长度8后Cnt累加到16 - 处理第三个子列表
list3时同理,for循环第一次迭代把num[0]的0赋值给num[16],原本的16被覆盖成0,取数时第一个元素就是0
这就是所有子列表都以0开头、8和16被跳过的原因,你处理百万级大列表时出现的所有子列表首元素被主列表第一个值替换的问题,也是完全相同的逻辑导致的。
你套的这层for循环本身完全是多余的——你已经在手动维护Cnt索引做顺序遍历,根本不需要再加一层for循环。
验证方法
你可以在每次处理子列表前打印原列表num,就能看到原列表的对应位置已经被篡改:处理list2前num[8]已经是0,处理list3前num[16]已经是0,和你最终的输出完全吻合。
修正代码
直接删掉多余的错误for循环即可,你写的while索引遍历逻辑本身是可以正常工作的,修正后代码如下:
list1 = [] list2 = [] list3 = [] LIST = [list1, list2, list3] num = list(range(25)) LastRow = len(num) Cnt = 0 target_len = 8 for listed in LIST: while len(listed) < target_len and Cnt < LastRow: listed.append(num[Cnt]) Cnt += 1 print(list1) print(list2) print(list3)
运行输出符合预期:
[0, 1, 2, 3, 4, 5, 6, 7] [8, 9, 10, 11, 12, 13, 14, 15] [16, 17, 18, 19, 20, 21, 22, 23]
更简洁的实现方式:对于固定长度的列表拆分,直接用切片实现即可,不需要手动维护索引,代码更短也不容易出错,示例:sub_lists = [num[i*target_len : (i+1)*target_len] for i in range(sub_list_count)],处理百万级数据时效率也更高。
内容的提问来源于stack exchange,提问作者Blewson
相关产品推荐
相关产品推荐

