how to convert code that uses cmp to python3

Chris Angelico rosuav at gmail.com
Thu Apr 7 08:22:08 EDT 2016


On Thu, Apr 7, 2016 at 10:05 PM, Antoon Pardon
<antoon.pardon at rece.vub.ac.be> wrote:
> I am looking at my avltree module for converting it to
> python3.
>
> One of the things that trouble me here is how python3 no
> longer has cmp and how things have to be of "compatible"
> type in order to be comparable.
>
> So in python2 it wasn't a problem to have a tree with
> numbers and strings as keys. In python3 that will not
> be so evident.
>
> In python2 descending the tree would only involve at
> most one expensive comparison, because using cmp would
> codify that comparison into an integer which would then
> be cheap to compare with 0. Now in python3, I may need
> to do two expensive comparisons, because there is no
> __cmp__ method, to make such a codefication.
>
> Is there a way to work around these limitations or
> should I resign myself to working within them?

First off, what does it actually *mean* to have a tree with numbers
and keys as strings? Are they ever equal? Are all integers deemed
lower than all strings? Something else?

Once you've figured out a sane definition, you can codify it one way
or another. For instance, if an integer is equal to a string
representing its digits, all you need to do is call str() on all keys.
Or if you want something like Python 2, where objects of different
types are sorted according to the names of the types, use this:

def keyify(obj):
    return (type(obj).__name__, obj)

All type names will be strings, so they're comparable. Only if the
type names are the same will the objects themselves be compared.
Alternatively, if the *only* types you handle are numbers and strings,
you could use this:

def keyify(obj):
    return (isinstance(obj, str), obj)

which lets all numbers group together, such that 1 < 2.0 < 3 as you'd
normally expect. All strings will be greater than all non-strings.

There's no __cmp__ method, but you could easily craft your own
compare() function:

def compare(x, y):
    """Return a number < 0 if x < y, or > 0 if x > y"""
    if x == y: return 0
    return -1 if keyify(x) < keyify(y) else 1

I'm not sure how your tree is crafted and how your "cheap" and
"expensive" comparisons previously worked, but give something like
this a try. I think you'll find it adequate.

ChrisA



More information about the Python-list mailing list