`for`-цикл в Python `sortedlist` не повторяется по всем элементам

Я пытаюсь просмотреть список, который растет во время цикла. Для больших списков я сталкиваюсь со странным поведением, итерация останавливается, прежде чем пройти через все элементы:

from blist import sortedlist

# for-loop
l = sortedlist(range(400))
for x in l:
    print(x)
    if x % 10 == 0:
        l.add(max(l) + 1)

print('last element:', l[-1])

# while-loop
l = sortedlist(range(400))
k = 0
while True:
    try:
        print(l[k])
        if l[k] % 10 == 0:
            l.add(max(l) + 1)
        k = k + 1
    except IndexError:
        break

print('last element:', l[-1])

Результаты:

.
.
.
430
431
last element: 443

.
.
.
443
444
last element: 444

Это не происходит для обычного списка. И "время цикла" проходит через все элементы, как я хочу. Я полагаю sortedlist хранятся в виде древовидных структур, и почему-то это не очень хорошо с модификацией списка во время цикла, но если у кого-то есть более глубокое понимание этого (и / или более ясный / лучший способ получить то же поведение, чем в цикле while))

Обратите внимание, что это не является критически важной частью производительности, поэтому я не возражаю против стоимости доступа к log (n) в случае "while-loop".

1 ответ

ОРИГИНАЛЬНЫЙ ОТВЕТ

Причина очень проста. Когда вы создаете цикл foreach над коллекцией, он сохраняет локальную копию информации списка, по которому он проходит. Это означает, что он только повторяет длину ваших исходных списков (безотносительно к любым изменениям).

Цикл while просто проверяет, выполняется ли условие для каждой итерации, и не сохраняет локальную копию информации вашего списка.

Модифицированный ответ

На основании вашего комментария я попытался воспроизвести его, но безуспешно. Однако это, кажется, производит то, что вы хотите:

l = sorted(range(400))
for x in l:
    print x
    if x%10 == 0:
        l.append(max(l)+1)

print str(l[-1])
Другие вопросы по тегам