Python operator: Sometimes True, sometimes False. What for?

I wanted to better understand OOP in Python and wrote some code describing (infinite) ordinal arithmetic. I have defined a named class with the Omega()

usual comparison operators ( ==

, <=

etc.), Addition and Multiplication.

I thought I would check how (as should be true) the first infinite ordinal added to itself was less than or equal to the first uncountable order. Launching an interactive shell, this is what I found:

    >>> a, b = Omega(), Omega(1)
    >>> (a+a) <= b
    False
    >>> (a+a) <= b
    True
    >>> (a+a) <= b
    False

      

The same expression expresses different truth values.

I kept testing the expression and couldn't find any pattern. If I re-interpret the code, I find that repeatedly testing the expression creates a different sequence of True

/ values False

.

What could be the reason for this behavior?

If this is relevant, I am using CPython 2.7.5 on Windows 8.1.

Here's the Python code I ran: http://pastebin.com/XPqMphBw

+3


source to share


2 answers


I believe that you overloaded the <=

and operators incorrectly >=

. Instead:

def __leq__(self, other):
# ...
def __geq__(self, other):

      

use this instead:



def __le__(self, other):
# ...
def __ge__(self, other):

      

After making these changes and running this in Python 3.4.1, I get:

>>> a, b = Omega(), Omega(1)
>>> (a+a) <= b
True
>>> (a+a) <= b
True
>>> (a+a) <= b
True

      

+6


source


Like @Padraic Cunningham, I also cannot replicate your problem (under Python 2.7.5 on Mac OS X). This gives me consistent answers.

You might find it helpful to provide the objects with an acceptable method __repr__

so that they can be easily printed out for debugging purposes. For example:

def __repr__(self):
    innards = ", ".join(str(v) for v in [self.index, self.power, self.copies])
    return "{0}({1})".format(self.__class__.__name__, innards)

      



The print a

then shows Omega(0, 1, 1)

. A slightly more favorable version might be:

def __repr__(self):
    innards = "index={index}, power={power}, copies={copies}".format(**self.__dict__)
    return "{0}({1})".format(self.__class__.__name__, innards)

      

I also note that your code probably doesn't compute "less than or equal to" as you think. You have established methods __leq__

and __geq__

, but they are not part of the Python data model . Instead, you want (and need) __le__

and __ge__

. If they are not defined, the combination of __eq__

and is called instead __lt__

. This combination usually has logical equivalence if you use the standard algebraic definition <=

, but in this case ... This is at least a place to check.

+1


source







All Articles