为何在Python for循环中需手动递增索引i才能得到预期结果?
问题解析:for循环中手动修改索引的原因
问题场景
我写了一段Python代码,想用正则表达式从列表sss中提取关键词,填充列表ben的缺失值。原代码输出不符合预期,但把else分支里的break换成i+=1后就得到了正确结果。我疑惑:外层for循环本身会自动迭代索引i,为什么还要手动递增i?
原代码
import re sss=['CP.NO.4-10-AHM-2017','CPNO.181-KB-2017','CPNo.224-5-MB-18','CPNo.224-5-GB-18','CPNo.224-5-KB-18','CPNo.224-5-MB-18'] ben = ['','KB','MB','','','MB'] itern = iter(sss) # 原代码中new_lst2应为sss,推测是笔误 for i,j in enumerate(ben): if not ben[i]: for k in itern: if re.search(r'(AHM|ahm|ALD|ald|AMR|amr|BB|bb|CHD|chd|CHE|che|CTB|ctb|GB|gb|HDB|hdb|JPR|jpr|KOC|koc|ND|nd|PB|pb|KB|kb|MB|mb|HRY|hry|KOB|kob)',k) == None: break else: a = re.search(r'(AHM|ahm|ALD|ald|AMR|amr|BB|bb|CHD|chd|CHE|che|CTB|ctb|GB|gb|HDB|hdb|JPR|jpr|KOC|koc|ND|nd|PB|pb|KB|kb|MB|mb|HRY|hry|KOB|kob)',k) ben[i] = a.group() break # 替换为i+=1后得到正确结果 print(ben)
输出对比
- 原代码输出:
['AHM', 'KB', 'MB', 'KB', 'MB', 'MB'] - 修改后输出:
['AHM', 'KB', 'MB', 'GB', 'KB', 'MB']
核心原因解析
外层循环的
i不受手动修改影响
外层for i,j in enumerate(ben)的i是由enumerate按顺序生成的固定序列(0,1,2,3,4,5),你在循环体内手动修改i的值,完全不会改变外层循环下一次迭代的i。比如你在i=0时把i改成100,下一次外层循环的i还是1。原代码的错误出在迭代器+break的组合
itern = iter(sss)创建的是状态化迭代器,每取一个元素就会向前推进指针,不会回头。原代码中,每次填充完一个空值就用break退出内层循环,导致迭代器指针停留在当前元素的下一个位置:
- 填充
ben[0]后,迭代器指向sss[1](KB) - 填充
ben[3]时,只能取到sss[1](KB)而非预期的sss[3](GB) - 填充
ben[4]时,取到sss[2](MB)而非sss[4](KB)
- 替换break为i+=1是巧合性修复
把break换成i+=1后,内层循环不会提前退出,会一次性遍历完整个迭代器:
- 内层循环会依次处理
sss的所有元素,同时手动递增i,刚好把ben的每个空值(索引0、3、4)对应到sss的同索引元素上 - 后续外层循环迭代到
i=1、2、3、4、5时,ben[i]已经被填充,不会再进入内层循环
这种写法是逻辑巧合,非常不严谨,一旦sss和ben长度不一致就会出错。
正确的写法
直接通过索引对应两个列表,逻辑清晰且不易出错:
import re sss=['CP.NO.4-10-AHM-2017','CPNO.181-KB-2017','CPNo.224-5-MB-18','CPNo.224-5-GB-18','CPNo.224-5-KB-18','CPNo.224-5-MB-18'] ben = ['','KB','MB','','','MB'] # 预编译正则并忽略大小写,提升效率 pattern = re.compile(r'(AHM|ALD|AMR|BB|CHD|CHE|CTB|GB|HDB|JPR|KOC|ND|PB|KB|MB|HRY|KOB)', re.IGNORECASE) for i in range(len(ben)): if not ben[i]: match = pattern.search(sss[i]) if match: ben[i] = match.group().upper() # 统一大写,保持格式一致 print(ben)
内容的提问来源于stack exchange,提问作者edox741
相关产品推荐
相关产品推荐

