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.

Morgan Kenyon
  • 3,072
  • 1
  • 26
  • 38
  • 1
    Is that your actual indentation? Also, note that `__cmp__` is ignored in 3.x, and was replaced by rich comparison: https://docs.python.org/3/reference/datamodel.html#object.__lt__. See e.g. http://stackoverflow.com/q/8276983/3001761 – jonrsharpe Feb 11 '15 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? – Morgan Kenyon Feb 11 '15 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. – jonrsharpe Feb 11 '15 at 22:09
  • What specifically is wrong about my indentation? What kind of indentation do you use? – Morgan Kenyon Feb 11 '15 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**. – jonrsharpe Feb 11 '15 at 22:11
  • You're right, I copied from my text editor and StackOverflow's code indentation messed up my indentation. The issues you point out are correct in my code. – Morgan Kenyon Feb 11 '15 at 22:12
  • So when you said *"that is my actual indentation"*, it actually isn't? Please **edit the question**. – jonrsharpe Feb 11 '15 at 22:13
  • No it wasn't. Sorry about that. – Morgan Kenyon Feb 11 '15 at 22:16

2 Answers2

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)
Adam Smith
  • 52,157
  • 12
  • 73
  • 112
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.