1

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?

jonrsharpe
  • 115,751
  • 26
  • 228
  • 437
gigatropolis
  • 229
  • 2
  • 7
  • 1
    Why exactly do they return self? The functions should return true or false, based on the outcome of comparison. This way, the outcome is always true, unless you've defined the boolean value of your class to be something else. – Fran Borcic Mar 11 '15 at 22:50

2 Answers2

4

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).

jonrsharpe
  • 115,751
  • 26
  • 228
  • 437
1

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)

Community
  • 1
  • 1