4

Just today I came accross about this strange behaviour of the in operator in Python (using Python 3.6.3 to be more specific).

>>> ':' in '4:2'
True
>>> ':' in '4:2' != True
True
>>> (':' in '4:2') != True
False
>>> ':' in ('4:2' != True)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: argument of type 'bool' is not iterable

As it can be seen, ':' in '4:2' is True. Everything normal here. But the strange behaviour appears in the second line:

>>> ':' in '4:2' != True
True

':' in '4:2' is True, which != True and results in… True? If we group by hand to ensure the precedence:

>>> (':' in '4:2') != True
False

Results in False. True != True is False as expected. Then, how did we get the True before?:

>>> ':' in ('4:2' != True)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: argument of type 'bool' is not iterable

What's going on?

Lonami
  • 5,945
  • 2
  • 20
  • 38
  • Related: [Why does this not work as an array membership test? \[duplicate\]](https://stackoverflow.com/q/40987185/953482) and [Why does the expression 0 < 0 == 0 return False in Python?](https://stackoverflow.com/q/6074018/953482) – Kevin Nov 16 '17 at 17:21
  • ':' in '4:2' != True: chaining operators – Jean-François Fabre Nov 16 '17 at 17:21
  • Well I knew about chaining operators like less (or equal to)/greater than, I just didn't know they applied to `in` too. How is this a duplicate for that question? It's clearly a different operator. – Lonami Nov 16 '17 at 17:23
  • When you explicitly put parentheses around it, you see the order in which you think the operators are evaluated. Without them you still think they are evaluated left to right, but they are not. Take a look here https://docs.python.org/2/reference/expressions.html#operator-precedence – Chrispresso Nov 16 '17 at 17:23
  • Semantically, `in` isn't a comparison operator, but syntactically it's treated like one, and so it participates in comparison chaining. – PM 2Ring Nov 16 '17 at 17:28
  • 2
    @Lonami It would be considered a duplicate since the answer to that question is "because of operator chaining", and there is no need to answer the same thing again for every other combination of operators. – bgse Nov 16 '17 at 17:28
  • @bgse I still can't see very well how "in" can chain at all with the rest operators. I think an answer on why this works like this for this case makes more sense than letting people figure out a completely different operator, more when `<` is so different from `in` (which accepts an iterator on the right side). – Lonami Nov 16 '17 at 17:31
  • The duplicate 40987185 does make more sense. Thanks, I guess. – Lonami Nov 16 '17 at 17:32
  • 1
    FWIW, there's nothing wrong with asking a question that gets closed as a dupe (provided it's not a really obvious dupe & you've done a search beforehand to find an existing question that addresses your problem). We close such questions because we don't want the answers to be scattered all over the place. It's much better if most of the relevant answers are in one place where people can easily compare and contrast them, and where those answers can be voted on as a group. – PM 2Ring Nov 16 '17 at 17:38
  • @Lonami, hopefully this helps.... `4 < 5 < 6` chains out to become `4 < 5 and 5 < 6`. Now we know that is true. You can also see that `4 < (5 < 6)` becomes `False` because what is inside parentheses is explicitly evaluated first. Using this on your example of `':' in '4:2' != True` this chains out to be `':' in '4.2' and '4.2' != True `. Once again, if you put the parentheses around it you no longer have a chained comparison. I hope this clears it up for you. – Chrispresso Nov 16 '17 at 17:49
  • Yes, thanks @ZWiki. The first duplicate they linked was a bit strange but the second made more sense. – Lonami Nov 16 '17 at 17:51

0 Answers0