2

I have this simple program that is supposed to sort the array of arrays by the key.

Why is the sorted() function saying that it only takes 1 argument, and that I am not providing any?

import operator

array = [[1, 6, 3], [4, 5, 6]]
sorted_array = sorted(iterable=array, key=operator.itemgetter(array[0][1]), reverse=True)
print(sorted_array)

And the error this gives:

Traceback (most recent call last):
  File "...", line 4, in <module>
    sorted_array = sorted(iterable=array, key=operator.itemgetter(array[0][1]), reverse=True)
TypeError: sorted expected 1 argument, got 0
Tomerikoo
  • 15,737
  • 15
  • 35
  • 52
Jake West
  • 101
  • 6
  • So what *does* it say? There can't be two different error messages at once. Please show the exact error traceback. – mkrieger1 Apr 03 '21 at 11:31
  • @mkrieger1 it does say both: TypeError: sorted expected 1 argument, got 0. – Jake West Apr 03 '21 at 11:37
  • sounds good @Ajay I will look into lambdas – Jake West Apr 03 '21 at 11:37
  • @Ajay Why? `operator` module is mostly used to ***replace*** the use of lambdas with pre-defined operator functions... i.e. instead of doing `lambda x,y: x + y` one would just use `operator.add`... – Tomerikoo Apr 03 '21 at 13:43

2 Answers2

6

Your confusion is justified. The error:

TypeError: sorted expected 1 argument, got 0

is a bit confusing to begin with. What it actually means is:

sorted expected 1 [positional] argument, got 0

Looking at the docs, the signature is:

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

According to this, a bare * in a function's signature means that all following arguments must be named. That doesn't say anything about the preceding arguments.

When printing help(sorted) in an interactive shell gives the more accurate signature:

sorted(iterable, /, *, key=None, reverse=False)

According to this, a / in a function's signature means that all preceding arguments must be positional, i.e. not named, which now explains the error. You just need to pass the array as a positional argument:

sorted_array = sorted(array, key=..., reverse=True)

Please refer to @Rivers' answer for the correct use of itemgetter as the key.


I have reported this documentation issue on the official Python bug tracker.

Tomerikoo
  • 15,737
  • 15
  • 35
  • 52
1

I'll try to give you a clear and detailed explanation:

There are 2 problems:

  1. iterable is not a named parameter
  2. itemgetter syntax is wrong

1 - Iterable:

This is the definition of the sorted function (see https://docs.python.org/3/library/functions.html#sorted): sorted(iterable, *, key=None, reverse=False)

Perhaps you thought that iterable is a named parameter, but it isn't. The named parameters are key and reverse (they have the equal sign (=) after their names).

So you don't have to write iterable=something. You just have to give an iterable data structure, so in your example that's the variable named array:

sorted_array = sorted(array,...)

Update: See @Tomerikoo answer for the exact reason why this didn't work in this case.

2 - Itemgetter: You can't write itemgetter(array[0][1]), you just have to give the indexes of the elements, so as @Ajay wrote in his comment, you could write this instead:

itemgetter(0,1)

But if you really want to sort by array[0][1], you should use a lambda function as @Ajay wrote too.

All in one:

from operator import itemgetter

array = [[1,6,3], [4,5,6]]
sorted_array = sorted(array, key=itemgetter(0,1), reverse=True)
print(sorted_array)

Output:

[[4, 5, 6], [1, 6, 3]]
Rivers
  • 1,482
  • 1
  • 6
  • 22
  • 1
    Please note that an argument doesn't become named by having a default value. It is completely fine to have `def foo(a): print(a)` and call it as `foo(a=5)`. Please see my answer for the real reason why this doesn't work – Tomerikoo Apr 03 '21 at 13:01