Along side the other answers that explain nicety , and this fact that python assign the elements in list to name friend in each iteration , you can use dis module to see in detail :
>>> def fun():
... friends = ['Bob','Luke','Ian', 'Frank']
... for friend in friends:
... print friend
...
>>> import dis
>>> dis.dis(fun)
2 0 LOAD_CONST 1 ('Bob')
3 LOAD_CONST 2 ('Luke')
6 LOAD_CONST 3 ('Ian')
9 LOAD_CONST 4 ('Frank')
12 BUILD_LIST 4
15 STORE_FAST 0 (friends)
3 18 SETUP_LOOP 19 (to 40)
21 LOAD_FAST 0 (friends)
24 GET_ITER
>> 25 FOR_ITER 11 (to 39)
28 STORE_FAST 1 (friend)
4 31 LOAD_FAST 1 (friend)
34 PRINT_ITEM
35 PRINT_NEWLINE
36 JUMP_ABSOLUTE 25
>> 39 POP_BLOCK
>> 40 LOAD_CONST 0 (None)
43 RETURN_VALUE
As you can see on following line, python began to assignment the friend and after each iteration it assigned again :
15 STORE_FAST 0 (friends)
The dis module supports the analysis of CPython bytecode by disassembling it. The CPython bytecode which this module takes as an input is defined in the file Include/opcode.h and used by the compiler and the interpreter
forstatement :)