Reputation: 141
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
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
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
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