358

I am trying to sort some values by attribute, like so:

a = sorted(a, lambda x: x.modified, reverse=True)

I get this error message:

<lambda>() takes exactly 1 argument (2 given)

Why? How do I fix it?


This question was originally written for Python 2.x. In 3.x, the error message will be different: TypeError: sorted expected 1 argument, got 2.

1
  • 12
    add keywoard argument key = lambda x: x.modified will solve the problem Commented Sep 22, 2010 at 5:53

5 Answers 5

560
+200

Use

a = sorted(a, key=lambda x: x.modified, reverse=True)
#             ^^^^

On Python 2.x, the sorted function takes its arguments in this order:

sorted(iterable, cmp=None, key=None, reverse=False)

so without the key=, the function you pass in will be considered a cmp function which takes 2 arguments.

Sign up to request clarification or add additional context in comments.

4 Comments

You have good chance to learn to appreciate keyword parameter passing from this experience.
This is very old but, do you have any idea why the error code is misleading? Your answer sounds like possible Python is supplying lambda with another parameter since a cmp function takes 2?
@SuperBiasedMan the error is not misleading. cmp, a comparator function takes two arguments. If you don't specify that you are passing a key, it is assumed from the function parameters order that you are passing a comparator. Your lambda takes one parameter, therefore is not a valid comparator and that's what the error says.
Python 2 and 3 seem to have different function declarations. I use Python 3, so there is no cmp anymore. In Python2, it is an iterable, what is it in Python 3?
88
lst = [('candy','30','100'), ('apple','10','200'), ('baby','20','300')]
lst.sort(key=lambda x:x[1])
print(lst)

It will print as following:

[('apple', '10', '200'), ('baby', '20', '300'), ('candy', '30', '100')]

5 Comments

This does not work for string integers. Check this out! lst = [('999', '9'), ('303', '30'), ('343', '34')] lst.sort(key=lambda x: x[1]) print(lst)
The result is [('303', '30'), ('343', '34'), ('999', '9')] which is not sorted base on the second element in every list.
lst = [('candy','999','9'), ('apple','303','30'), ('baby','343','34')] lst.sort(key=lambda x:x[2]) print(lst)
[('apple', '303', '30'), ('baby', '343', '34'), ('candy', '999', '9')]. Which is not sorted base on 2 element too!
@DanielKua That's pretty simple to fix. You can just do int(x[1]) instead of just x[1].
15

You're trying to use key functions with lambda functions.

Python and other languages like C# or F# use lambda functions.

Also, when it comes to key functions and according to the documentation

Both list.sort() and sorted() have a key parameter to specify a function to be called on each list element prior to making comparisons.

...

The value of the key parameter should be a function that takes a single argument and returns a key to use for sorting purposes. This technique is fast because the key function is called exactly once for each input record.

So, key functions have a parameter key and it can indeed receive a lambda function.

In Real Python there's a nice example of its usage. Let's say you have the following list

ids = ['id1', 'id100', 'id2', 'id22', 'id3', 'id30']

and want to sort through its "integers". Then, you'd do something like

sorted_ids = sorted(ids, key=lambda x: int(x[2:])) # Integer sort

and printing it would give

['id1', 'id2', 'id3', 'id22', 'id30', 'id100']

In your particular case, you're only missing to write key= before lambda. So, you'd want to use the following

a = sorted(a, key=lambda x: x.modified, reverse=True)

Comments

11

Take a look at this Example, you will understand:

Example 1:

a = input()
a = sorted(a, key = lambda x:(len(x),x))
print(a)

input: ["tim", "bob", "anna", "steve", "john","aaaa"]
output: ['bob', 'tim', 'aaaa', 'anna', 'john', 'steve']

input: ["tim", "bob", "anna", "steve", "john","aaaaa"]
output: ['bob', 'tim', 'anna', 'john', 'aaaaa', 'steve']


Example 2 (advanced):

a = ["tim", "bob", "anna", "steve", "john","aaaaa","zzza"]
a = sorted(a, key = lambda x:(x[-1],len(x),x))
print(a)

output: ['anna', 'zzza', 'aaaaa', 'bob', 'steve', 'tim', 'john']


Example 3 (advanced):

a = [[1,4],[2,5],[3,1],[1,6],[3,8],[4,9],[0,3],[2,6],[9,5]]
a = sorted(a, key = lambda x:(-x[1],x[0]))
print(a)

output: [[4, 9], [3, 8], [1, 6], [2, 6], [2, 5], [9, 5], [1, 4], [0, 3], [3, 1]]


Conclusion:

key = lambda x:(p1,p2,p3,p4,...,pn),
x is one element at a time from the stream of input.
p1,p2,p3...pn being properties based on which the stream of elements needs to be sorted.
based on priority order of p1>p2>p3>...>pn.
We can also add reverse=True, after the sorting condition, to sort the elements in reverse order.

Comments

11

In Python3:

from functools import cmp_to_key
def compare(i1,i2):
  return i1-i2
events.sort(key=cmp_to_key(compare))

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.