There are many kinds of chained operators (in some languages even associative arithmetic operators are chained). Contrary to popular beliefs, this is nothing to do with chained operators but rather with operator precedences.<p>It is pretty common that arithmetic comparison operators are grouped to a single precedence level and that's not a problem. But in Python `is`, `is not`, `in` and `not in` are also in that level. In particular two operands of `in` and `not in` have different [1] types unlike others. Mixing them are, either with or without chained operators, almost surely incorrect.<p>This kind of precedence issue can be solved by introducing non-associative pairs of operators (or precedence levels), something that---unfortunately---I don't see much in common programming languages. Ideally Python's operator precedence table should look like this (compare with the current documentation [2]):<p><pre><code> Operator Description
-------------------------------------- ------------------------
... ...
`not x` Boolean NOT
_______________________________________________________________
|
| The following groups do not mix to each other.
| Use parentheses to clarify what you mean.
| ______________________________________________________________
||
|| `in`, `not in` Membership tests
||
|| `is`, `is not` Identity tests
||
|| `<`, `<=`, `>`, `>=`, `!=`, `==` Comparisons
||______________________________________________________________
|_______________________________________________________________
`|` Bitwise OR
... ...
</code></pre>
In fact, there is already one non-associative pair in Python: `not` and virtually every operator except boolean operators. It is understandable: the inability to parse `3 + not 4` is marginal but you don't want `3 is not 4` to be parsed as `3 is (not 4)`. My point is that, if we already have such a pair why can't we have more?<p>[1] With an exception of strings (`"a" in "abcdef"`). I hate that Python doesn't have a character type.<p>[2] <a href="https://docs.python.org/3.8/reference/expressions.html#operator-precedence" rel="nofollow">https://docs.python.org/3.8/reference/expressions.html#opera...</a>