列表len()在for循环每次迭代会重算吗?DataFrame列删除遇索引越界求解
Hey,咱们逐个解决你的问题哈:
问题1:for循环迭代时,列表的len()函数是否会被重新计算?
得分两种常见场景来看:
- 如果你是用
for i in range(len(my_list))这种写法:len(my_list)只会在循环开始前计算一次。因为range()会基于这个初始长度生成一个固定的整数序列,之后哪怕你在循环里修改了列表长度,这个序列也不会跟着变。 - 但如果是在循环体内部每次调用
len(my_list),或者用for item in my_list直接迭代列表:前者每次调用len()都会重新计算当前列表的实时长度;后者的迭代器会动态感知列表变化(不过这种情况下在循环里删元素很容易踩坑,比如跳过某些元素)。
问题2:列表索引越界错误的原因及解决方法
你猜的完全正确!这个错误确实和列表长度变化有关,具体原因是这样的:
当你写for i in range(len(columnstokeep))时,len(columnstokeep)在循环启动的瞬间就算出了初始长度,比如假设初始有10列,range(10)会生成0到9的索引序列。但每次执行columnstokeep.remove(columnstokeep[i]),列表长度就会减1——比如删了一个元素后长度变成9,但循环还是会按0到9的索引去遍历。当i走到原来的最大索引(比如9)时,此时列表的最大索引已经是8了,自然就抛出索引越界错误。
而且还有个隐藏坑:就算没触发越界,正向循环删元素时,后面的元素会往前移位,导致你跳过了一些元素的检查(比如删除索引2的元素后,原来索引3的元素变成了索引2,但下一次循环i会变成3,直接漏掉了这个元素)。
给你两种更靠谱的解决方法:
方法1:倒序循环遍历
倒着遍历索引,这样就算删除前面的元素,也不会影响当前正在处理的索引位置:
columnstokeep = list(DF) # 从最后一个索引倒着往前循环 for i in range(len(columnstokeep)-1, -1, -1): if int(columnstokeep[i][:4]) < 2000: columnstokeep.remove(columnstokeep[i]) DF = DF[columnstokeep]
方法2:列表推导式筛选(更简洁高效)
直接生成符合条件的列名列表,比循环删除更直观,也完全避开了列表修改带来的问题,推荐优先用这个:
columnstokeep = [col for col in DF.columns if int(col[:4]) >= 2000] DF = DF[columnstokeep]
内容的提问来源于stack exchange,提问作者ZakS
相关产品推荐
相关产品推荐

