It depends on the implementation and version of python and how persistent lists are used. On Cpython2.7.10 with your example, it seems like the answer is that the list in the state of the if is created only once ...
>>> def foo(): ... for i in iterable: ... if i in [1, 3, 5]: ... print(i) ... >>> import dis >>> dis.dis(foo) 2 0 SETUP_LOOP 34 (to 37) 3 LOAD_GLOBAL 0 (iterable) 6 GET_ITER >> 7 FOR_ITER 26 (to 36) 10 STORE_FAST 0 (i) 3 13 LOAD_FAST 0 (i) 16 LOAD_CONST 4 ((1, 3, 5)) 19 COMPARE_OP 6 (in) 22 POP_JUMP_IF_FALSE 7 4 25 LOAD_FAST 0 (i) 28 PRINT_ITEM 29 PRINT_NEWLINE 30 JUMP_ABSOLUTE 7 33 JUMP_ABSOLUTE 7 >> 36 POP_BLOCK >> 37 LOAD_CONST 0 (None) 40 RETURN_VALUE
Note: 16 LOAD_CONST 4 ((1, 3, 5))
The Peeon peephole optimizer turned our list into a tuple (thanks python!) And saved it as a constant. Please note that the spy optimizer can only perform these transformations on objects if it knows that you, since the programmer has absolutely no way to get a link to a list (otherwise you can change the list and change the meaning of the code). As far as I know, they do this optimization only for list , set literals, which consist of completely constants and are the RHS of the in operator. There may be other cases that I do not know about ( dis.dis is your friend for finding these optimizations).
I hinted at it above, but you can do the same with set-literals in later versions of python (in python3.2 +, set converted to frozenset constant). The advantage is that set / frozenset have faster average membership testing than list / tuple .
mgilson
source share