gigatropolis
gigatropolis

Reputation: 257

Chain overloaded comparison operators

I want to do something like this:

MyClass > 200 < 400  

The class implements the __gt__() and __lt__() methods and they both return self.

class MyClass:

    ...

    def __gt__(self, value):
        DoCompareStuff(self, value)
        return self

    def __lt__(self, value):
        DoCompareStuff(self, value)
        return self

   ...

It will do the first evaluation, MyClass > 200, but never performs the second, MyClass < 400. It seems like Python is doing something with the return value like making it True or False. Is there a way to do what I'm trying to do here?

Upvotes: 1

Views: 524

Answers (2)

user764357
user764357

Reputation:

First of all, this code doesn't make sense:

MyClass > 200 < 400 

As it expands to:

MyClass > 200 and 200 < 400 

Which resolves to:

MyClass > 200

Secondly, Python has a strong concept of "truthiness" when it comes to boolean values. Which means in essence, anything that is not zero-ish is "true".

Lastly, when you have this code:

def __gt__(self, value):
    DoCompareStuff(self, value)
    return self

Since self will be an object of some type, it will always, always* be true. For example both of these will evaluate to true, because you are returning self:

10 < MyClassInstance
10 > MyClassInstance

* sometimes, except when you implement the __bool__ method. (Thanks @wim)

Upvotes: 2

jonrsharpe
jonrsharpe

Reputation: 122024

Operator chaining for comparisons (see the docs) means that

MyClass > 200 < 400 

is actually evaluated as:

(MyClass > 200) and (200 < 400)

therefore no comparison between MyClass and 400 is ever made. Instead, you want:

200 < MyClass < 400

which is evaluated as:

(200 < MyClass) and (MyClass < 400)

For a simpler example:

>>> class Demo(object):

    def __init__(self, value):
        self.value = value

    def __lt__(self, other):
        return self.value < other

    def __gt__(self, other):
        return self.value > other


>>> demo = Demo(250)
>>> 200 < demo < 400
True

Note that the __lt__ and __gt__ implementations here have a Boolean return (True or False), rather than returning self (which will lead to unexpected behaviour).

Upvotes: 4

Related Questions