Top and Bottom Values [PEP: 326]

Steven D'Aprano steve at REMOVE.THIS.cybersource.com.au
Wed Sep 27 10:32:54 EDT 2006


On Wed, 27 Sep 2006 13:37:40 +0000, Paul McGuire wrote:

> Here's a little more refined version of my previous post:
> 
> class StubbornInt(int):
>     def invariantOp(self,other):
>         return self
>     __add__ = invariantOp
>     __sub__ = invariantOp

[snip rest of code]

> import sys
> Top = StubbornInt(sys.maxint)

Top shouldn't need to depend on a specific integer value, but then it is
easy enough to subclass StubbornInt.

However, there is a more serious problem with your definition of Top:

>>> Top > sys.maxint+1
False

But Top is supposed to bigger than everything, right?

Okay, let's fix it:

class FixedTop(StubbornInt):
    def __init__(self):
        super(FixedTop, self).__init__(sys.maxint)
        self.name = 'Top'
    def _bigger(self, other):
        # Top is bigger than everything
        return True
    def _smaller(self, other):
        # Top is smaller than nothing
        return False
    __lt__ = __le__ = _smaller
    __gt__ = __ge__ = _bigger


Let's test it out:

>>> Top = FixedTop()
>>> Top > 45
True
>>> Top > sys.maxint
True
>>> Top > 2L**512
True
>>> Top > None
True
>>> Top > "hello"
True


So far so good.

However, the downside of rolling your own Top is the risk that one day
you'll have something like this:

class Funny:
    def __init__(self, name):
        self.name = name
    def __str__(self):
        return self.name
    def __gt__(self, other):
        return len(str(self)) > len(str(other))

and then you'll have problems:

>>> bottom = Funny("Bottom")
>>> Top > bottom
True
>>> bottom > Top
True

As far as I can see, the only way to avoid edge cases like this is for Top
(and Bottom) to be built-ins that are special-cased by Python.



-- 
Steven.




More information about the Python-list mailing list