custom sorting and __cmp__

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Lee Harr

    custom sorting and __cmp__


    Let's say I have a class

    class A:
    def __init__(self, level):
    self.level = level

    and I want to put some of these in a list and sort the list
    by level

    a1 = A(1)
    a2 = A(2)
    l = [a1, a2]
    l.sort()

    Am I better off creating a __cmp__ method for my class or
    making a cmp function to pass to sort?


    My thought was that __cmp__ would be perfect, but then I
    started thinking about this ...
    [color=blue][color=green][color=darkred]
    >>> class A:[/color][/color][/color]
    .... def __init__(self, level):
    .... self.level = level
    .... def __cmp__(self, other):
    .... if self.level > other.level:
    .... return 1
    .... elif self.level < other.level:
    .... return -1
    .... else:
    .... return 0
    ....[color=blue][color=green][color=darkred]
    >>> a1 = A(1)
    >>> a2 = A(2)
    >>> class C:[/color][/color][/color]
    .... pass
    ....[color=blue][color=green][color=darkred]
    >>> c = C()
    >>> a1 == a2[/color][/color][/color]
    False[color=blue][color=green][color=darkred]
    >>> a1 < a2[/color][/color][/color]
    True[color=blue][color=green][color=darkred]
    >>> a1 == c[/color][/color][/color]
    Traceback (most recent call last):
    File "<stdin>", line 1, in ?
    File "<stdin>", line 5, in __cmp__
    AttributeError: C instance has no attribute 'level'


    Should I be catching comparisons to objects that do not have
    my 'level' attribute and falling back to id comparison?
    Or am I worried about nothing (YAGNI :o) ?


    Is this related in any way to interfaces?

  • Emile van Sebille

    #2
    Re: custom sorting and __cmp__

    Lee Harr[color=blue]
    > My thought was that __cmp__ would be perfect, but then I
    > started thinking about this ...
    >[color=green][color=darkred]
    > >>> class A:[/color][/color]
    > ... def __init__(self, level):
    > ... self.level = level
    > ... def __cmp__(self, other):
    > ... if self.level > other.level:
    > ... return 1
    > ... elif self.level < other.level:
    > ... return -1
    > ... else:
    > ... return 0[/color]

    Instead, how about:
    def __cmp__(self,ot her):
    try: return cmp(self.level, other.level)
    except return 1 # or -1

    --

    Emile van Sebille
    emile@fenx.com

    Comment

    • Kristian Ovaska

      #3
      Re: custom sorting and __cmp__

      Lee Harr <missive@fronti ernet.net>:[color=blue]
      >Should I be catching comparisons to objects that do not have
      >my 'level' attribute and falling back to id comparison?[/color]

      I usually solve it like this:

      class A:
      def __init__(self, level):
      self.level = level

      def __cmp__(self, other):
      if isinstance(othe r, A):
      return cmp(self.level, other.level)
      else:
      return -1

      --
      Kristian Ovaska - http://www.cs.helsinki.fi/u/hkovaska/

      Comment

      • Aahz

        #4
        Re: custom sorting and __cmp__

        In article <slrnbsk5ms.1pe .missive@homer. easthighschool. net>,
        Lee Harr <missive@hotmai l.com> wrote:[color=blue]
        >[color=green][color=darkred]
        >>>> a1 == c[/color][/color]
        >Traceback (most recent call last):
        > File "<stdin>", line 1, in ?
        > File "<stdin>", line 5, in __cmp__
        >AttributeError : C instance has no attribute 'level'
        >
        >Should I be catching comparisons to objects that do not have
        >my 'level' attribute and falling back to id comparison?
        >Or am I worried about nothing (YAGNI :o) ?[/color]

        Python is these days moving more and more toward preventing
        heterogeneous comparisons:
        [color=blue][color=green][color=darkred]
        >>> import datetime, time
        >>> d=datetime.date .fromtimestamp( time.time())
        >>> d>1[/color][/color][/color]
        Traceback (most recent call last):
        File "<stdin>", line 1, in ?
        TypeError: can't compare datetime.date to int

        However, you should set things up so that you can use ``==``:
        [color=blue][color=green][color=darkred]
        >>> d==1[/color][/color][/color]
        False

        The easy way to handle this is to use the new special methods for rich
        comparisons instead of __cmp__.
        --
        Aahz (aahz@pythoncra ft.com) <*> http://www.pythoncraft.com/

        Weinberg's Second Law: If builders built buildings the way programmers wrote
        programs, then the first woodpecker that came along would destroy civilization.

        Comment

        Working...