Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Minimum Methods for Ordering with Duck Typing in Python 3.1

In the manual is says:

in general, __lt__() and __eq__() are sufficient, if you want the conventional meanings of the comparison operators

But I see the error:

>       assert 2 < three
E       TypeError: unorderable types: int() < IntVar()

when I run this test:

from unittest import TestCase

class IntVar(object):

    def __init__(self, value=None):
        if value is not None: value = int(value)
        self.value = value

    def __int__(self):
        return self.value

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

    def __eq__(self, other):
        return self.value == other

    def __hash__(self):
        return hash(self.value)

class DynamicTest(TestCase):

    def test_lt(self):
        three = IntVar(3)
        assert three < 4
        assert 2 < three
        assert 3 == three

I am surprised that when IntVar() is on the right, __int__() is not being called. What am I doing wrong?

Adding __gt__() fixes this, but means I don't understand what the minimal requirements are for ordering...

Thanks, Andrew

like image 899
andrew cooke Avatar asked Oct 08 '22 04:10

andrew cooke


1 Answers

Python 3.x will never do any type coercions for operators, so __int__() is not used in this context. The comparison

a < b

will first try to call type(a).__lt__(a, b), and if this returns NotImplemented, it will call type(b).__gt__(b, a).

The quote from the documentation is about making comparisons work for a single type, and the above explanation shows why this would be enough for a single type.

To make your type interact correctly with int, you should either implement all the comparison operator, or use the total_ordering decorator available in Python 2.7 or 3.2.

like image 184
Sven Marnach Avatar answered Oct 12 '22 20:10

Sven Marnach