Simplify Chained Comparison

Simplify Chained Comparison

In Python you can "chain" comparison operations which just means they are "and"ed together. In your case, it'd be like this:

if start <= x <= end:

Reference: https://docs.python.org/3/reference/expressions.html#comparisons

PyCharm: “Simplify Chained Comparison”

Your expression can be rewritten as:

if cnt_1 < 0 <= cnt_2:

This is called comparison chaining.

what is PyCharm simplify chained comparison

@mhlester should get the credit for noting that you can drop the >= clauses from the conditions as they are already implicit since you are using elif. However, you could also condense things more if you wanted by putting your data in a tuple then indexing in to it.

return ('E', 'M', 'P', 'L', 'N')[x / 25] # This assumes x has an upper bound of 124 or less.

Of course, in this particular instance, you could make your life even simpler.

return random.choice(('E', 'M', 'P', 'L', 'N'))

Can you simplify chained comparisons with not equal or equal in Python?

this is functionnaly equivalent, but when this:

10 < x < 40

is nice to read, mixing different operators to use chained comparisons isn't the best choice.

Is that really the same? let's disassemble to find out:

def f1(x,y):
if y > x and x != -1:
return 0

def f2(x,y):
if y > x != -1:
return 0

import dis

print("function 1")
dis.dis(f1)
print("function 2")
dis.dis(f2)

result:

function 1
2 0 LOAD_FAST 1 (y)
3 LOAD_FAST 0 (x)
6 COMPARE_OP 4 (>)
9 POP_JUMP_IF_FALSE 28
12 LOAD_FAST 0 (x)
15 LOAD_CONST 3 (-1)
18 COMPARE_OP 3 (!=)
21 POP_JUMP_IF_FALSE 28

3 24 LOAD_CONST 2 (0)
27 RETURN_VALUE
>> 28 LOAD_CONST 0 (None)
31 RETURN_VALUE
function 2
6 0 LOAD_FAST 1 (y)
3 LOAD_FAST 0 (x)
6 DUP_TOP
7 ROT_THREE
8 COMPARE_OP 4 (>)
11 JUMP_IF_FALSE_OR_POP 23
14 LOAD_CONST 3 (-1)
17 COMPARE_OP 3 (!=)
20 JUMP_FORWARD 2 (to 25)
>> 23 ROT_TWO
24 POP_TOP
>> 25 POP_JUMP_IF_FALSE 32

7 28 LOAD_CONST 2 (0)
31 RETURN_VALUE
>> 32 LOAD_CONST 0 (None)
35 RETURN_VALUE
>>>

Surprisingly they aren't the same, and the chained version has more instructions.

Not sure what's going on here (some took some more time to explain it better: How do chained comparisons in Python actually work?), but really I'd stick to the and version which shortcuts and is so much readable (think of future maintainers too...).

That said, one interesting thing about chained comparisons would be if the central argument is computed/takes a long time to compute/has a side effect in the computation and you don't want to store it in a variable:

if y > super_long_computation(x) != -1:

In that case, the central argument is only evaluated once. In the case of and, you'd have to store it beforehand.

Can this chained comparison really be simplified like PyCharm claims?

IIRC, you could rewrite this as:

while self._xp < 0 < self.level:
self.level -= 1
self._xp += self.get_xp_quota()

as per your reference above. It doesn't really matter that there's 2 different attributes or the same variable, ultimately you are simply comparing the values of each.

Let me know if that works.

Python chained comparison

An example of a chained comparison is shown below.

age = 25

if 18 < age <= 25:
print('Chained comparison!')

Note that beneath the covers this is exactly the same as shown below, it just looks nicer.

age = 25

if 18 < age and age <= 25:
print('Chained comparison!')


Related Topics



Leave a reply



Submit