Suppose we want some block of code to be executed when both \'a\' and \'b\' are equal to say 5. Then we can write like :
if a == 5 and b == 5:
# do something
As far as integers are concerned, there is no difference, in terms of sheer performance, between the first two comparisons.
The third comparison is different, though; since a little more fiddling with the stack gets involved. Indeed, the code
import dis
def comparison_1(a, b):
if a == 5 and b == 5:
pass
def comparison_2(a, b):
if a == b and b == 5:
pass
def comparison_3(a, b):
if a == b == 5:
pass
print("*** First comparison ***")
dis.dis(comparison_1)
print("\n*** Second comparison ***")
dis.dis(comparison_2)
print("\n*** Third comparison ***")
dis.dis(comparison_3)
returns
*** First comparison ***
4 0 LOAD_FAST 0 (a)
3 LOAD_CONST 1 (5)
6 COMPARE_OP 2 (==)
9 POP_JUMP_IF_FALSE 27
12 LOAD_FAST 1 (b)
15 LOAD_CONST 1 (5)
18 COMPARE_OP 2 (==)
21 POP_JUMP_IF_FALSE 27
5 24 JUMP_FORWARD 0 (to 27)
>> 27 LOAD_CONST 0 (None)
30 RETURN_VALUE
*** Second comparison ***
8 0 LOAD_FAST 0 (a)
3 LOAD_FAST 1 (b)
6 COMPARE_OP 2 (==)
9 POP_JUMP_IF_FALSE 27
12 LOAD_FAST 1 (b)
15 LOAD_CONST 1 (5)
18 COMPARE_OP 2 (==)
21 POP_JUMP_IF_FALSE 27
9 24 JUMP_FORWARD 0 (to 27)
>> 27 LOAD_CONST 0 (None)
30 RETURN_VALUE
*** Third comparison ***
12 0 LOAD_FAST 0 (a)
3 LOAD_FAST 1 (b)
6 DUP_TOP
7 ROT_THREE
8 COMPARE_OP 2 (==)
11 JUMP_IF_FALSE_OR_POP 23
14 LOAD_CONST 1 (5)
17 COMPARE_OP 2 (==)
20 JUMP_FORWARD 2 (to 25)
>> 23 ROT_TWO
24 POP_TOP
>> 25 POP_JUMP_IF_FALSE 31
13 28 JUMP_FORWARD 0 (to 31)
>> 31 LOAD_CONST 0 (None)
34 RETURN_VALUE