Переназначение зацикливаемой переменной не имеет никакого эффекта, потому что переменная не переоценивается для каждой итерации. Фактически, цикл внутренне проходит по итератору , а не по вашему range
объекту.
В основном, если у вас есть такой цикл:
seq = range(5)
for elem in seq:
seq = something_else
Python переписывает это примерно так:
seq = range(5)
loop_iter = iter(seq) # obtain an iterator
while True:
try:
elem = next(loop_iter) # get the next element from the iterator
except StopIteration:
break # the iterator is exhausted, end the loop
# execute the loop body
seq = something_else
Важнейшим аспектом этого является то, что цикл имеет собственную ссылку на iter(seq)
, сохраненную в loop_iter
, поэтому естественное переназначение seq
не влияет на цикл.
Все это объясняется в документации составного оператора :
for_stmt ::= "for" target_list "in" expression_list ":" suite
["else" ":" suite]
Список выражений вычисляется один раз; это должно привести к повторяемости
объект. Итератор создан для результата expression_list
.
Затем набор выполняется один раз для каждого элемента, предоставленного
итератор, в порядке, возвращенном итератором.