Home > OS >  Python order of execution of logic check
Python order of execution of logic check

Time:01-21

So my boss came up with this (by accident) after a quick search and replace on the code and opening a Pull Request, where tag is always a string:

if "team_" in tag in tag:

To my surprise, that actually works! Not really sure why. I was expecting to parse it from left to right and get an error, like this

>>> ("team_" in "something") in "something"
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'in <string>' requires string as left operand, not bool

or even in the worst case, parse it from right to left (which I find it odd, but let's assume it works that way)

>>> "team_" in ("something" in "something")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: argument of type 'bool' is not iterable

but what I got instead was

>>> "team_" in "something" in "something"
False
>>> 
>>> "some" in "something" in "something"
True
>>> 

can someone explain to me how/why does that work?

CodePudding user response:

It works for the same reason that

1 < x < 10

works. Python allows comparison operators to be chained, so this is equivalent to

1 < x and x < 10

By the same logic

"team_" in tag in tag

is equivalent to

"team_" in tag and tag in tag

When tag is a string, this is effectively equivalent to just "team_" in tag, since a string is always in itself. But if tag is a list or other container it will usually be false because a container doesn't usually contain an instance of itself (it's possible to make recursive references, e.g. mylist.append(mylist), and then mylist in mylist would be true).

CodePudding user response:

You're witnessing chained comparisons (a more classic example being something like a < b < c)

"some" in "something" in "something"

is the same as

("some" in "something") and ("something" in "something")

so it's valid.

But if you protect one side with parentheses,

("some" in "something") in "something"
     aka   True         in "something"

then you generate a boolean on one side, which explains the error message (the error message is different depending on the side, in the left case it refuses to look for a boolean in a string, and in the right case it refuses to iterate on a boolean)

Yes this natural language stuff is treacherous and can accidentally compile (see a classic issue: How to test multiple variables for equality against a single value?)

  • Related