Though the print("f called")
is only called once, the variable (called iterable object
which stores the evaluation value of enumerate(printmylist(mylist))
in your case has its referred set
change from time to time because you remove the enumeration one by one. At first you have all the 100 items, but it is reduced one by one:
Note: len(mylist) - i - 1 = 99, delete index 99 -> 100 removed
1 2 3 ... 98 99 100 #len(mylist) = 100
^ <-- here is i = 0
Note: len(mylist) - i - 1 = 98, delete index 98 -> 99 removed
1 2 3 ... 98 99 #len(mylist) = 99
^ <-- here is i = 1
Note: len(mylist) - i - 1 = 97, delete index 97 -> 98 removed
1 2 3 ... 98 #len(mylist) = 98
^ <-- here is i = 2
... and so on
Plus, since i
will be checked every end of the loop against that variable (the iterable object
, therefore, you only print 50
items out of 100
items.
From the Python for statement documentation:
The expression list is evaluated once; it should yield an iterable
object. An iterator is created for the result of the expression_list
.
The suite is then executed once for each item provided by the
iterator, in the order of ascending indices. Each item in turn is
assigned to the target list using the standard rules for assignments,
and then the suite is executed. When the items are exhausted (which is
immediately when the sequence is empty), the suite in the else
clause,
if present, is executed, and the loop
terminates.
To simplify, imagine you have
v = enumerate(printmylist(mylist)) #v is the iterable object
Though it is only evaluated once, the set
where v
is pointed to changes every time you remove an item but i
iterates over v
. Thus, i
is going to be increasing increasing till finally i = 50
.
.
.
.
v = ... 50, i = 49
^ <-- here is i and is in v
v = ... 50 , i = 50 and is out from v
^ <-- no more item found
No more item is left to be evaluated beyond the border. Thus you get the results:
100 99 ... 51
And not getting out of bounds.
More on how for works internally, including how it creates internal indexer and checks it against the value pointed by the termination value every time.