Along side the other answers that explains the short-circuiting
, The both do one job and there is no much difference between the performance.
See the following benchmark :
s1="""
for i in range(1,1000):
if i % 3==0 and i %5 == 0:
pass
"""
s2="""
for i in range(1,1000):
if i%3==0:
if i%5==0:
pass
"""
print ' first: ' ,timeit(stmt=s1, number=1000)
print 'second : ',timeit(stmt=s2, number=1000)
Result :
first: 0.0738339424133
second : 0.0790829658508
as you can see the difference is 0.006
and its because of an extra block loading in the second part.
Also you can use dis
module for disassembling the python bytecode :
first loop using and
:
21 0 SETUP_LOOP 58 (to 61)
3 LOAD_GLOBAL 0 (range)
6 LOAD_CONST 1 (1)
9 LOAD_CONST 2 (1000)
12 CALL_FUNCTION 2
15 GET_ITER
>> 16 FOR_ITER 41 (to 60)
19 STORE_FAST 0 (i)
22 22 LOAD_FAST 0 (i)
25 LOAD_CONST 3 (3)
28 BINARY_MODULO
29 LOAD_CONST 4 (0)
32 COMPARE_OP 2 (==)
35 POP_JUMP_IF_FALSE 16
38 LOAD_FAST 0 (i)
41 LOAD_CONST 5 (5)
44 BINARY_MODULO
45 LOAD_CONST 4 (0)
48 COMPARE_OP 2 (==)
51 POP_JUMP_IF_FALSE 16
23 54 JUMP_ABSOLUTE 16
57 JUMP_ABSOLUTE 16
>> 60 POP_BLOCK
>> 61 LOAD_CONST 0 (None)
64 RETURN_VALUE
and for second :
26 0 SETUP_LOOP 61 (to 64)
3 LOAD_GLOBAL 0 (range)
6 LOAD_CONST 1 (1)
9 LOAD_CONST 2 (1000)
12 CALL_FUNCTION 2
15 GET_ITER
>> 16 FOR_ITER 44 (to 63)
19 STORE_FAST 0 (i)
27 22 LOAD_FAST 0 (i)
25 LOAD_CONST 3 (3)
28 BINARY_MODULO
29 LOAD_CONST 4 (0)
32 COMPARE_OP 2 (==)
35 POP_JUMP_IF_FALSE 16
28 38 LOAD_FAST 0 (i)
41 LOAD_CONST 5 (5)
44 BINARY_MODULO
45 LOAD_CONST 4 (0)
48 COMPARE_OP 2 (==)
51 POP_JUMP_IF_FALSE 60
29 54 JUMP_ABSOLUTE 60
57 JUMP_ABSOLUTE 16
>> 60 JUMP_ABSOLUTE 16
>> 63 POP_BLOCK
>> 64 LOAD_CONST 0 (None)
67 RETURN_VALUE