The list
iterator in CPython works by iterating over the positions of the list. You can think of it working like this:
def list_iter(items: list):
index = 0
while True:
yield items[index]
index += 1
In other words, iteration provides the item at 0, then 1, then 2, and so on. There is no pre-fetching of items - an item is looked up from the list when needed.
As you delete the first item on every step, the list is shortened by 1 on each step. Since you start with a list of 6 items, on the third iteration it is down to 3 items - meaning the fourth iteration fails to look up an item. Thus, your iteration finishes after three steps.
You can see this when printing also the current element in each loop. To visualise the effect, use enumerate
to get the index of the iteration. Notice that it advances by one index, but the values are also shifted for a total offset of two:
>>> a = [1, 2, 3, 4, 5, 6]
... for idx, elem in enumerate(a):
... print(elem, 'from', a)
... print(' ', ' '*idx, '^')
... del a[0]
...
1 from [1, 2, 3, 4, 5, 6]
^
3 from [2, 3, 4, 5, 6]
^
5 from [3, 4, 5, 6]
^
It is generally not well-defined to modify a container while iterating over it. You should iterate over a copy instead:
a = [1, 2, 3, 4, 5, 6]
for elem in a.copy():
del a[0]
print(a)