Let's look at the bytecode:
>>> def so25807731():
... word = "hello"
... for word in word:
... print word
...
>>> import dis
>>> dis.dis(so25807731)
2 0 LOAD_CONST 1 ('hello')
3 STORE_FAST 0 (word)
3 6 SETUP_LOOP 19 (to 28)
9 LOAD_FAST 0 (word)
12 GET_ITER
>> 13 FOR_ITER 11 (to 27)
16 STORE_FAST 0 (word)
4 19 LOAD_FAST 0 (word)
22 PRINT_ITEM
23 PRINT_NEWLINE
24 JUMP_ABSOLUTE 13
>> 27 POP_BLOCK
>> 28 LOAD_CONST 0 (None)
31 RETURN_VALUE
Notice how first, Python grabs an iterator for the string (GET_ITER
) and loops through that, rather than the actual string (FOR_ITER
).
Therefore, it doesn't need the original string to "remember" what the characters were; it simply uses the newly created iterator for that. The "old word
" value is effectively no longer used, so you can overwrite it without problems. Similar logic explains why this code can work as well:
word = "llamas"
for character in word:
word = None
print character