我去,困扰我小半个上午的问题终于悟到了。。。
得到两个很简单但平时不怎么注意到的结论:
- for循环在每次循环时都会更新判断条件中的变量值,相当于每次判断的时候都会以变量最新值来判断是否满足循环条件,而不是一直保持初次进行判断时候的值。如
for col in cols:
如果循环体中改变了cols
,那么下次循环时cols
就按最新的来。 for col in cols:
看着像是以cols
中的元素值进行判断,其实使用的是索引,每次循环其实改变的是索引i
,col
是以索引取出的值cols[i]
。结合上一条容易发现如果在循环体中改变了cols
,那结果显然会与预期不符。
上述描述可能还比较抽象,下面记录一下今天上午犯的小迷糊。
问题发生:
为了描述方便和问题呈现的直观性,我定义一个list来复现我遇到的问题。
我的目的是删除cols
中包含[MAX]\[max]\[MIN]\[min]
字符的元素。代码如下:
filterlist = ['[MAX]','[MIN]','[max]','[min]']
cols = ['WTUR_Temp_Ra_F32_TowerBase[MAX]', 'WGEN_Temp_Ra_F32_4[AVG]', 'WTPS_Temp_Ra_F32_Pcap3[MAX]', 'WTPS_Temp_Ra_F32_gen3[MIN]',
'WGEN_Temp_Ra_F32_1[MAX]', 'WNAC_Temp_Ra_F32[MIN]', 'WYAW_CTim_Rt_F32_Ygen[min]', 'WGEN_Spd_Ra_F32_overspblade1[AVG]']
for col in cols:
for filt in filterlist:
if filt in col:
cols.remove(col)
print(cols)
出人意料的是,得到的结果竟然是这样的:
['WGEN_Temp_Ra_F32_4[AVG]', 'WTPS_Temp_Ra_F32_gen3[MIN]', 'WNAC_Temp_Ra_F32[MIN]', 'WGEN_Spd_Ra_F32_overspblade1[AVG]']
问题寻解:
我真的百思不得其解。。因为这块代码逻辑很简单,就死活没想出来究竟哪里出问题了,但结果又是错的,于是就在能想到的可能出现的问题的地方print
了一下,豁然开朗。。。
调试代码如下:
filterlist = ['[MAX]','[MIN]','[max]','[min]']
cols = ['WTUR_Temp_Ra_F32_TowerBase[MAX]', 'WGEN_Temp_Ra_F32_4[AVG]', 'WTPS_Temp_Ra_F32_Pcap3[MAX]', 'WTPS_Temp_Ra_F32_gen3[MIN]',
'WGEN_Temp_Ra_F32_1[MAX]', 'WNAC_Temp_Ra_F32[MIN]', 'WYAW_CTim_Rt_F32_Ygen[min]', 'WGEN_Spd_Ra_F32_overspblade1[AVG]']
i = 0
for col in cols:
i += 1
print(i,cols,col)
for filt in filterlist:
if filt in col:
cols.remove(col)
打印结果:
1 ['WTUR_Temp_Ra_F32_TowerBase[MAX]', 'WGEN_Temp_Ra_F32_4[AVG]', 'WTPS_Temp_Ra_F32_Pcap3[MAX]', 'WTPS_Temp_Ra_F32_gen3[MIN]', 'WGEN_Temp_Ra_F32_1[MAX]', 'WNAC_Temp_Ra_F32[MIN]', 'WYAW_CTim_Rt_F32_Ygen[min]', 'WGEN_Spd_Ra_F32_overspblade1[AVG]'] WTUR_Temp_Ra_F32_TowerBase[MAX]
2 ['WGEN_Temp_Ra_F32_4[AVG]', 'WTPS_Temp_Ra_F32_Pcap3[MAX]', 'WTPS_Temp_Ra_F32_gen3[MIN]', 'WGEN_Temp_Ra_F32_1[MAX]', 'WNAC_Temp_Ra_F32[MIN]', 'WYAW_CTim_Rt_F32_Ygen[min]', 'WGEN_Spd_Ra_F32_overspblade1[AVG]'] WTPS_Temp_Ra_F32_Pcap3[MAX]
3 ['WGEN_Temp_Ra_F32_4[AVG]', 'WTPS_Temp_Ra_F32_gen3[MIN]', 'WGEN_Temp_Ra_F32_1[MAX]', 'WNAC_Temp_Ra_F32[MIN]', 'WYAW_CTim_Rt_F32_Ygen[min]', 'WGEN_Spd_Ra_F32_overspblade1[AVG]'] WGEN_Temp_Ra_F32_1[MAX]
4 ['WGEN_Temp_Ra_F32_4[AVG]', 'WTPS_Temp_Ra_F32_gen3[MIN]', 'WNAC_Temp_Ra_F32[MIN]', 'WYAW_CTim_Rt_F32_Ygen[min]', 'WGEN_Spd_Ra_F32_overspblade1[AVG]'] WYAW_CTim_Rt_F32_Ygen[min]
第一次打印的就是最开始的cols
,这是没问题的,包括col
也是cols
中第一个元素。但是第二次起,问题就表现出来了,此时的cols
已经是上一步移除了第一个元素后的cols
,而for
循环又是按照list
的索引在取元素,这是第二次循环,因此要取此时cols
中的第二个元素,于是'WGEN_Temp_Ra_F32_4[AVG]'
就被跳过了。同样地,第三次for循环,取第三个元素,'WGEN_Temp_Ra_F32_4[AVG]','WTPS_Temp_Ra_F32_gen3[MIN]'
, 这两个就被跳过去了,后面同理。这样下来,很多元素被跳过了比较,结果自然就与我以为的有所偏差。找到病症,就好解决了。
两个思路:1.保证for循环时cols不变,只改变元素索引 2.可以改变cols,但是要保证每次都是拿当前cols中第一个元素进行比较。
我选择了第一种,最终实现了我预期功能的代码如下:
filterlist = ['[MAX]','[MIN]','[max]','[min]']
cols = ['WTUR_Temp_Ra_F32_TowerBase[MAX]', 'WGEN_Temp_Ra_F32_4[AVG]', 'WTPS_Temp_Ra_F32_Pcap3[MAX]', 'WTPS_Temp_Ra_F32_gen3[MIN]',
'WGEN_Temp_Ra_F32_1[MAX]', 'WNAC_Temp_Ra_F32[MIN]', 'WYAW_CTim_Rt_F32_Ygen[min]', 'WGEN_Spd_Ra_F32_overspblade1[AVG]']
drop = []
for col in cols:
for filt in filterlist:
if filt in col:
drop.append(col)
rem = list(set(cols)-set(drop))
print(rem)
输出:
['WGEN_Temp_Ra_F32_4[AVG]', 'WGEN_Spd_Ra_F32_overspblade1[AVG]']