tyranno
tyranno

Reputation: 141

TypeError; Must use key word argument or key function in Python 3.x

I am new to Python, trying to port a script in 2.x to 3.x i am encountering the error "TypeError; must use key word argument or key function" in Python 3.x. Below is the piece of code.

def resort_working_array(self, chosen_values_arr, num):
    for item in self.__working_arr[num]:
        data_node = self.__pairs.get_node_info(item)

        new_combs = []
        for i in range(0, self.__n):
            # Numbers of new combinations to be created if this item is appended to array
            new_combs.append( set([pairs_storage.key(z) for z in xuniqueCombinations( chosen_values_arr+[item], i+1)]) - self.__pairs.get_combs()[i] )
        # Weighting the node
        item.weights =  [-len(new_combs[-1])]  # Node that creates most of new pairs is the best
        item.weights += [len(data_node.out)]   # Less used outbound connections most likely to produce more new pairs while search continues
        item.weights += [len(x) for x in reversed(new_combs[:-1])]
        item.weights += [-data_node.counter]   # Less used node is better
        item.weights += [-len(data_node.in_)]  # Otherwise we will prefer node with most of free inbound connections; somehow it works out better ;)

    self.__working_arr[num].sort(key = lambda a,b: cmp(a.weights, b.weights))

Upvotes: 11

Views: 25224

Answers (3)

Jeremy Davis
Jeremy Davis

Reputation: 750

Following on from the answer by @Kevin - and more specifically the comment/question by @featuresky:

Using functools.cmp_to_key and reimplementing cmp (as noted in the porting guide) I have a hacky workaround for a scenario where two elements can be compared via lambda form. To use the OP as an example; instead of:

self.__working_arr[num].sort( key = lambda a,b: cmp(a.weights, b.weights) )

You can use this:

from functools import cmp_to_key

[...]

def cmp(x, y): return (x > y) - (x < y)
self.__working_arr[num].sort(key=cmp_to_key(lambda a,b: cmp(a.weights, b.weights)))

Admittedly, I'm somewhat new to Python myself and don't really have a good handle on Python 2. I'm sure the code could be rewritten in a much better/cleaner way and I'd certainly love to hear a "proper" way to do this.

On the other hand, in my case this was a handy hack for a old Python 2 script (updated to Python 3) that I don't have time/energy to "properly" understand and rewrite right now.

Beyond the fact that it works, I would certainly not recommend wide usage of this hack! But I figured that it was worth sharing.

Upvotes: 0

Jarekczek
Jarekczek

Reputation: 7866

The exact same error message appears if you try to pass the key parameter as a positional parameter.

Wrong:

sort(lst, myKeyFunction)

Correct:

sort(lst, key=myKeyFunction)

Python 3.6.6

Upvotes: 7

Kevin
Kevin

Reputation: 76194

Looks like the problem is in this line.

self.__working_arr[num].sort( key = lambda a,b: cmp(a.weights, b.weights) )

The key callable should take only one argument. Try:

self.__working_arr[num].sort(key = lambda a: a.weights)

Upvotes: 21

Related Questions