Это классическая разрушительная итерация. Что вы делаете это:
>>> l= [0, 1, 2, 3, 4]
>>> for n in l:
... l.remove(n)
...
>>> l
[1, 3]
В этом примере удаляется только каждый второй элемент. Зачем? Хорошо, синтаксис for
... in
скрывает то, что происходит на самом деле, что аналогично традиционному циклу for-index в стиле C:
>>> l= [0, 1, 2, 3, 4]
>>> i= 0
>>> while i<len(l):
... del l[i]
... i+= 1
...
>>> l
[1, 3]
Таким образом, первый раз в цикле i
равен 0. Элемент 0 удаляется, перемещая элементы 1–4 вниз на одно место, чтобы быть новыми элементами 0–3. В следующий раз цикл i
равен 1
, поэтому текущий элемент 1, который равен 2
, удаляется. Оригинал 1
был перепрыгнут и остается в цикле.
Простой обходной путь, позволяющий избежать разрушительной итерации, - это взять копию списка и выполнить итерацию копии при изменении оригинала:
for handler in list(my_logger.handlers):
Использование filter
или списочных представлений обычно является более простым способом, когда вы пытаетесь удалить определенные элементы из списка.