1

I am attempting to implement a priority queue in Python. I am following an example that I found online. The Skill class overrides the __cmp__ method so that the priority queue can order itself. I am getting a error when I run:

TypeError: unorderable types: Skill() < Skill()

I've found several examples online that say as long as you overload the __cmp__() method the priority queue should be good.

try:
    import Queue as Q  # ver. < 3.0
except ImportError:
    import queue as Q

class Skill(object):
    def __init__(self, priority, description):
        self.priority = priority
        self.description = description
        print ('New Level:', description)
        return
    def __cmp__(self, other):
        return cmp(self.priority, other.priority)

q = Q.PriorityQueue()

q.put(Skill(5, 'Proficient'))
q.put(Skill(10, 'Expert'))
q.put(Skill(1, 'Novice'))

while not q.empty():
    next_level = q.get()
    print ('Processing level:', next_level.description)

I'm currently running Python 3.4.1 on my computer.

8
  • 1
    Is that your actual indentation? Also, note that __cmp__ is ignored in 3.x, and was replaced by rich comparison: docs.python.org/3/reference/datamodel.html#object.__lt__. See e.g. stackoverflow.com/q/8276983/3001761 Commented Feb 11, 2015 at 22:06
  • That is my actual indentation. I'm new to Python, is another indentation more common? So I should use a rich comparison rather than cmp? Commented Feb 11, 2015 at 22:08
  • Indentation is crucial in Python, the code you've posted won't work. Yes, you have to use the rich comparison methods if you're writing for 3.x. Commented Feb 11, 2015 at 22:09
  • What specifically is wrong about my indentation? What kind of indentation do you use? Commented Feb 11, 2015 at 22:10
  • The body of Skill.__init__ isn't indented, and __cmp__ is shown as being outside of the class altogether. What do you mean "what kind"?! Indentation is part of Python's syntax. Commented Feb 11, 2015 at 22:11

2 Answers 2

4

__cmp__ was removed in Python3, you should use the rich comparison dunder methods instead __lt__, __le__, __eq__, __ne__, __gt__, __ge__.

They work as follows:

a < b  # a.__lt__(b)
a <= b # a.__le__(b)
a == b # a.__eq__(b)
a != b # a.__ne__(b)
a > b  # a.__gt__(b)
a >= b # a.__ge__(b)

You can also use the the class decorator functools.total_ordering which allows you to specify __eq__ and any one of __lt__, __le__, __gt__, __ge__ and it will infer the rest of the rich comparison methods.

import functools

@functools.total_ordering
class NewNumber(object):
    def __init__(self, num):
        self.num = num
    def __lt__(self, other):
        return self.num < getattr(other, 'num', other)
        # fancy way of doing self.num < other.num if other.num exists,
        #   else to do self.num < other
    def __eq__(self, other):
        return self.num == getattr(other, 'num', other)
Sign up to request clarification or add additional context in comments.

Comments

1

cmp and __cmp__ were only used in Python 2.x; they no longer exist in Python 3.x. Nowadays, you overload the comparison operators directly by implementing __eq__, __ne__, __lt__, __gt__, __ge__, and __le__.

You can read about this change on the What's New In Python 3.0 page under Ordering Comparisons:

The cmp() function should be treated as gone, and the __cmp__() special method is no longer supported. Use __lt__() for sorting, __eq__() with __hash__(), and other rich comparisons as needed.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.