acdr - 8 months ago 35

Python Question

Python allows expressions like

`x > y > z`

`(x > y) and (y > z)`

`y`

However, this seems to break if I customize comparison functions. E.g. suppose I have the following class: (Apologies for the large block, but once you read the

`__eq__`

`class CompareList(list):`

def __repr__(self):

return "CompareList([" + ",".join(str(x) for x in self) + "])"

def __eq__(self, other):

if isinstance(other, list):

return CompareList(self[idx] == other[idx] for idx in xrange(len(self)))

else:

return CompareList(x == other for x in self)

def __ne__(self, other):

if isinstance(other, list):

return CompareList(self[idx] != other[idx] for idx in xrange(len(self)))

else:

return CompareList(x != other for x in self)

def __gt__(self, other):

if isinstance(other, list):

return CompareList(self[idx] > other[idx] for idx in xrange(len(self)))

else:

return CompareList(x > other for x in self)

def __ge__(self, other):

if isinstance(other, list):

return CompareList(self[idx] >= other[idx] for idx in xrange(len(self)))

else:

return CompareList(x >= other for x in self)

def __lt__(self, other):

if isinstance(other, list):

return CompareList(self[idx] < other[idx] for idx in xrange(len(self)))

else:

return CompareList(x < other for x in self)

def __le__(self, other):

if isinstance(other, list):

return CompareList(self[idx] <= other[idx] for idx in xrange(len(self)))

else:

return CompareList(x <= other for x in self)

Now I can do fun stuff like

`CompareList([10, 5]) > CompareList([5, 10])`

`CompareList([True,False])`

However, chaining these operations doesn't work nicely:

`low = CompareList([1])`

high = CompareList([2])

print(low > high > low) # returns CompareList([True])

Why not? What happens under the hood here? I know it isn't equivalent to

`(low > high) > low`

`(False > low)`

`low > (high > low)`

Answer

Python allows expressions like

`x > y > z`

, which, according to the docs, is equivalent to`(x > y) and (y > z)`

except`y`

is only evaluated once.

According to this, `low > high > low`

will be equivalent to `(low > high) and (high > low)`

.

```
>>> x = low > high # CompareList([False])
>>> y = high > low # CompareList([True])
>>> x and y
CompareList([True])
```

More from the documentation on x and y:

`x and y`

: if`x`

is false, then`x`

, else`y`

In the above case:

```
>>> x is False
False
>>> x if x is False else y # x and y
CompareList([True])
```

so when you do `x and y`

it returns the `y`

which is `CompareList([True])`

.