Reputation: 21
I'm trying to gain some insight in to why I'm receiving an error message.
I'm trying to sort a dictionary using a custom function. I realize I can use lambda to achieve the same goal, as well as sorting the dictionary in to tuples first, but what I'm really trying to do is understand why my function isn't returning a list.
sample_dict = {"a":4,"b":2,"c":7,"d":9}
def all_values(x):
return list(x.values())
print(sorted(sample_dict, key = all_values))
Expecting for return list(x.values()) to return a list to be used in the sorted key argument, but instead, I'm given the error message:
AttributeError: 'str' object has no attribute 'values'
Upvotes: 2
Views: 96
Reputation: 1858
I think you've been confused by the way key
argument works.
Essentially, it maps a given function over all elements of your iterable, and then sorted
sorts based on the outputs of the mapping.
In fact, when you sort sample_dict
, you are sorting its keys, which are strings:
sample_dict = {"b":2, "c":7, "d":9, "a":4}
print(sorted(sample_dict))
# ['a', 'b', 'c', 'd']
and if I try to map all_values
to this list of strings:
list(map(all_values, sample_dict))
# AttributeError: 'str' object has no attribute 'values'
all_values
must get a string in input then, like @Jean-FrançoisFabre suggests:
def all_values(x):
return sample_dict[x]
print(sorted(sample_dict, key = all_values))
# ['b', 'a', 'c', 'd']
Upvotes: 0
Reputation: 140168
you mean to sort the keys according to the values.
The key
function is meant to convert the dictionary key to something comparable (if you omit it, it's like passing an identity function, you're comparing on the dictionary key itself). You want to return the value from the key, so it's a dictionary access:
sample_dict = {"a":4,"b":2,"c":7,"d":9}
def all_values(x):
return sample_dict[x]
print(sorted(sample_dict, key = all_values))
You were expecting the dictionary to be passed in the key
, which would have no interest at all. key
must be different at each call sort
does.
Using a lambda
is of course shorter
print(sorted(sample_dict, key = lambda x: sample_dict[x]))
but passing a real function allows to insert side effects more easily:
def all_values(x):
print("key input",x)
return sample_dict[x]
with that you get an insight of what sort
is doing (and the final result is printed by the main print statement):
key input b
key input a
key input c
key input d
['b', 'a', 'c', 'd']
and now you understand why list('b'.values())
failed.
Upvotes: 3