ewilulu
ewilulu

Reputation: 193

TypeError: 'cmp' is an invalid keyword argument for this function

I'm using Python3, but the script is not compatible with this version and I hit some errors. Now I have problem with cmp parameter. Here is the code

def my_cmp(x,y):
    counter = lambda x, items: reduce(lambda a,b:a+b, [list(x).count(xx) for xx in items])
    tmp =  cmp(counter(x, [2,3,4,5]), counter(y, [2,3,4,5]))
    return tmp if tmp!=0 else cmp(len(x),len(y)) 

for i, t in enumerate([tmp[0] for tmp in sorted(zip(tracks, self.mapping[idx][track_selection[-1]].iloc[0]), cmp=my_cmp, key=lambda x:x[1])]):
    img[i,:len(t)] = t

I would really appreciate any help how to deal with this error in Python3.

Upvotes: 16

Views: 18462

Answers (2)

user3506100
user3506100

Reputation: 141

from python documentation

In Python 2.7, the functools.cmp_to_key() function was added to the functools module.

The function available in python 3 too.

Just wrap your cmp function with cmp_to_key

from functools import cmp_to_key

...

...key=cmp_to_key(my_cmp)...

Upvotes: 13

Martijn Pieters
Martijn Pieters

Reputation: 1124968

You should try to rewrite your cmp function to a key function instead. In this case it looks like you can simply return the counter() function output for just one element:

def my_key(elem):
    counter = lambda x, items: sum(list(x).count(xx) for xx in items)
    return counter(elem, [2, 3, 4, 5]), len(elem)

I took the liberty of replacing the reduce(...) code with the sum() function, a far more compact and readable method to sum a series of integers.

The above too will first sort by the output of counter(), and by the length of each sorted element in case of a tie.

The counter function is hugely inefficient however; I'd use a Counter() class here instead:

from collections import Counter

def my_key(elem):
    counter = lambda x, items: sum(Counter(i for i in x if i in items).values())
    return counter(elem, {2, 3, 4, 5}), len(elem)

This function will work in both Python 2 and 3:

sorted(zip(tracks, self.mapping[idx][track_selection[-1]].iloc[0]),
       key=lambda x: my_key(x[1]))

If you cannot, you can use the cmp_to_key() utility function to adapt your cmp argument, but take into account this is not an ideal solution (it affects performance).

Upvotes: 3

Related Questions