循环中的副作用会影响生成器吗?
在Python 2.7中,我遇到了一个关于for
循环的情况,这个循环是基于一个for
生成器的。在循环的主体部分,作为for
生成器来源的那个项目发生了变化:
for ssid in (ssid for ssid in overlaps if ssid != subseq_id):
overlaps = subseq_id_to_overlap_ssids_dict[ssid]
我想问的是,这种对overlaps
的变化是否会影响到for
生成器?我希望不会,但如果会的话,那具体意味着什么呢?如果我处理了第一个匹配的元素,然后替换了overlaps
,那么for
会不会指向overlaps
的新值的下一个位置呢?
2 个回答
一个 for
循环的工作原理是,它会对给定的内容进行迭代,也就是先调用 iter
函数来生成一个迭代器,然后不断调用 next
来获取下一个元素,直到遇到 StopIteration
这个信号,表示没有更多元素了。
在你使用生成器表达式时,overlaps
这个名字会在进入 for
循环之前就被计算出来,所以如果你在循环中重新给 overlaps
赋值,它是不会有任何影响的。不过,如果你改变了 overlaps
所指向的对象,那么效果就会有所不同,这取决于 type(overlaps)
的迭代器是怎么工作的。举个例子,list
的迭代器会在列表中逐个增加索引。
在循环里面重新绑定 overlaps
其实对循环没有影响(当然,如果修改它的话就会有影响)。在循环内部重新绑定 subseq_iq
可能会影响生成器。
for
循环在开始的时候只会评估一次表达式,以获取一个迭代器:在这个例子中,表达式就是 overlaps
的名字。一旦评估了这个表达式,它就会从可迭代对象中创建一个迭代器,并用这个迭代器来逐个处理元素。这个迭代器是依赖于表达式返回的对象,而不是依赖于用来标识这个对象的名字(如果有名字的话)。
在这个特定的情况下,代码实际上和下面的内容是完全一样的:
for ssid in overlaps:
if ssid != subseq_id:
overlaps = subseq_id_to_overlap_ssids_dict[ssid]
这样写会更清晰,但再次强调,重新绑定 overlaps
并不会改变 for
循环所使用的序列。