Source

Weird Comparison Issue in Python

Hi guys! I am back with a new article. This time I will tackle a problem which seems easy enough at first but will surprize some of you. Suppose you have the following piece of code:

a = 3
b = False
c = """12"""
d = 4.7

and you have to evaluate this:

d + 2 * a > int(c) == b

Before reading the rest of the post please take a minute to solve this statement in your head and try to come up with the answer.

So while solving it my thought process went something like this:

2 * a = 6
d + 6 = 10.7
10.7 > int(c) is equal to False
False == b is equal to True 

But lo-and-behold. If we run this code in Python shell we get the following output:

False

Dang! What went wrong there? Was our thinking wrong? I am pretty sure it was supposed to return True. I went through the official docs a couple of times but couldn’t find the answer. There was also a possibility in my mind that this might be some Python 2 bug but when I tried this code in Python 3 I got the same output. Finally, I turned to the Python’s IRC channel which is always full of extremely helpful people. I got my answer from there.

So I got to know that I was chaining comparisons. But I knew that already. What I didn’t know was that whenever you chain comparisons, Python compares each thing in order and then does an “AND”. So our comparison code is equivalent to:

(d + 2*a) > (int(c)) and (int(c)) == (b)

This brings us to the question that whenever you chain comparisons, does Python compares each thing in order and then does an “AND”?

As it turns out this is exactly what Python does: x <comparison> y <comparison> z is executed just like x <comparison> y and y <comparison> z, except y is only evaluated once.

I hope you found this article helpful. If you have any questions, comments, suggestions please feel free to reach out to me via email or the comments section below.

Newsletter

Ă—

If you liked what you read then I am sure you will enjoy a newsletter of the content I create. I send it out every other month. It contains new stuff that I make, links I find interesting on the web, and occasional discount coupons for my book. Join the 5000+ other people who receive my newsletter:

I send out the newsletter once every other month. No spam, I promise + you can unsubscribe at anytime

✍️ Comments

codeinfig

first of all, cool post. once it is known how python handles this, the obvious workaround (use parentheses to force python to handle things in the order we prefer) is:

(d + 2 * a > int(c)) == b

and that fixes your problem. now if you want to tell me that pythons way of handling d + 2 * a > int(c) == b is weird and un-obvious: i agree. i wouldnt have guessed that (d + 2 * a > int(c)) == b fixes it until i read your post. but at least the fix is easy and intuitive– once the piece of knowledge youre sharing here is known.

phihag

Yes, that’s the downside of chained comparisons. As a general rule of thumb, you should use parentheses whenever you are not 100% sure: Even if your code was right already, parentheses make it much more easier to read for people who are less experienced than you.

By the way, don’t you mean that y is only evaluated once?

Yasoob
In reply to phihag

Yes you are right. Thanks for catching this error. Let me edit the post.

retard

No shit, the same thing happens with this: if ‘a’ <= foo <= ďż˝zďż˝: return True

Say something

Send me an email when someone comments on this post.

Thank you!

Your comment has been submitted and will be published once it has been approved. 😊

OK