Tobin
Tobin

Reputation: 2159

Why do these two codes give the same result?

CODE 1:

>>> data = ['A', 'B', 'C', 'D']
>>> for i, x in enumerate(data, 1):
        print(i, x)

CODE 2:

>>> data = ['A', 'B', 'C', 'D']
>>> for i, x in enumerate(data, 1):
        print(i, x)
        i += 1

RESULT (for both):

1 A
2 B
3 C
4 D

Why does incrementing in the second code have no effect on the result?

Upvotes: 1

Views: 115

Answers (2)

Brian61354270
Brian61354270

Reputation: 14474

Some insight can be found by taking a look at the byte code that CPython produces in your second example:

>>> from dis import dis                                                                                           
>>> def with_increment(): 
        for i, x in enumerate(data, 1): 
            print(i, x) 
            i += 1                                                                                                              
>>> dis(with_increment)                                                                                           
  2           0 SETUP_LOOP              40 (to 42)
              2 LOAD_GLOBAL              0 (enumerate)
              4 LOAD_GLOBAL              1 (data)
              6 LOAD_CONST               1 (1)
              8 CALL_FUNCTION            2
             10 GET_ITER
        >>   12 FOR_ITER                26 (to 40)
             14 UNPACK_SEQUENCE          2
             16 STORE_FAST               0 (i)
             18 STORE_FAST               1 (x)

  3          20 LOAD_GLOBAL              2 (print)
             22 LOAD_FAST                0 (i)
             24 LOAD_FAST                1 (x)
             26 CALL_FUNCTION            2
             28 POP_TOP

  4          30 LOAD_FAST                0 (i)
             32 LOAD_CONST               1 (1)
             34 INPLACE_ADD
             36 STORE_FAST               0 (i)
             38 JUMP_ABSOLUTE           12
        >>   40 POP_BLOCK
        >>   42 LOAD_CONST               0 (None)
             44 RETURN_VALUE

The part we're interested in is bytes 12-38, which correspond to the body of the loop. Each iteration starts by performing the following actions in sequence:

  • UNPACK_SEQUENCE 2 - The components of the tuple produced by enumerate are pushed onto the stack.

  • STORE_FAST 0 - The value on the top of the stack is stored in the first local variable (i).

  • STORE_FAST 1 - The value on the top of the stack is stored in the second local variable (x).

The key thing to note here is that we never look at the current value of i---each iteration blindly overwrites it with whatever was produced by the iterator. Whatever object used to be in i during the previous iteration is completely forgotten.

Upvotes: 1

Samwise
Samwise

Reputation: 71542

The i value you get from the iteration is the output of the enumerate function, not an input to it.

Modifying it does not affect the course of the enumeration, and the for...in loop will continually overwrite the variable with whatever enumerate produces, regardless of what you set it to within the loop body.

Unlike Java and C, loops in python iterate over iterables. They don't depend on counters.

Upvotes: 3

Related Questions