*Here's a Python 'gotcha' I spotted in this StackOverflow question the other day. It's not something that's ever bitten me, but I thought it was interesting enough to write a quick post about.*

Anyone who's used Python for a good length of time has probably come across the idea of operator chaining. In languages like C, to check that a value was in a certain range, you'd do something like this:

```
if ((low <= x) && (x < upper)){
// Do something here!
}
```

It's fairly concise, but it gets ugly pretty quickly if there's more than a couple of conditions.

In Python, it's a lot simpler - just use the mathematical style of 'chaining' operators:

```
if low <= x < upper:
# Do something here!
```

The documentation for operator precedence can be found here. The operators `in`

, `not in`

, `is`

, `is not`

, `<`

, `<=`

, `>`

, `>=`

, `!=`

and `==`

all have the same precedence which gives some strange results, like the one referenced in the StackOverflow question above.

Consider the expression `x in y == True`

, where `x`

is some object such that `x in y`

evaluates to `True`

and `y`

is some object such that `y != True`

.

The obvious, wrong answer is that the expression evaluates to `True`

. In fact:

```
>>> x in y
True
>>> x in y == True
False
```

This assumption turns out to be false. The logical next step is that there's an operator precedence issue - but we've just ascertained that `in`

and `==`

have the *same* precedence. Instead of correcting it immediately, we can try to reproduce the error more clearly:

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

Makes sense - but it raises the question of how exactly the original expression is evaluating to `False`

, instead of either evaluating to `True`

or raising a `TypeError`

.

The answer lies in the chaining demonstrated above: what's really happening is this:

```
(x in y) and (y == True)
```

Since `y`

is presumably some sequence (or custom object with a `__contains__`

method), we know it's definitely not equal to `True`

.

To get the result we want, of course, we just put the first expression in brackets:

```
(x in y) == True
```

Although, in practice, it's not worth checking for equality to a boolean - just checking if the result is truthy or falsy will likely be enough:

```
if x in y:
# Do something!
```

I've never once written - or personally come across, besides that SO question - any code that chains operators of that precedence other than the "limit" operators. It's hard to think of where `x in y in z`

would ever come in handy, although I'd concede that `x != y != z`

might be a neat way to save a few characters if you're code-golfing (with the spaces removed, of course!).

Edit: I just came across another possibility for where chaining mixed operators could come in handy:

```
if x < f() != y:
# Do something!
```

We save some screen space by eliminating a variable for the two checks against the function's return value - `f()`

is only evaluated once, whereas the following would evaluate it twice:

```
x < f() and f() != y
```

But really, minimising vertical space shouldn't be of a higher priority than code clarity, and this works just as well:

```
result = f()
if x < result and result != y:
# Do something!
```