Nirbhay Garg
Nirbhay Garg

Reputation: 97

why sorted() in python didn't accept positional arguments?

a=[1,2,3,4]
def func(x):
   return x**x

b=sorted(a,func)

this line always gives a error->

TypeError: sorted expected 1 argument, got 2

in fact the syntax of sorted is sorted(iterable,key,reverse), in which key and reverse are optional, so according to this, second parameter i pass must go with key.

and when i def my own func

def func2(x,y=4,z=10):
    print(x,y,z)
func2(100,200)--->output-->>100 200 10

here 200 automatically passed as y argument for func2. How does this work?

Upvotes: 7

Views: 1942

Answers (2)

user4815162342
user4815162342

Reputation: 154886

why sorted() in python doesn't accept positional arguments?

Because sorted used to accept positional arguments in Python 2, but the second argument was the comparison function, not the key function as it is now. Python 3 dropped support for comparison function in list.sort and sorted was modified accordingly. It was deemed too confusing to silently change the meaning of a poositional argument, so the devs decided to completely forbid positional arguments (except for the very first argument, the iterable to sort), and require keyword arguments for everything else.

The intention is for unmodified Python 2 code that calls sorted(sequence, function) to fail fast in Python 3, instead of attempting to call the comparison function as a key function, calling it with an incorrect number of arguments. This prevents confusion that might ensue if the comparison function happened to accept a variable number of arguments, or if the sequence were empty so the sort happened to "work" for some inputs.

Likewise, sorted(sequence, cmp=function) fails early due to cmp having been removed. sorted(sequence, key=function) works as intended in both Python 2 and 3.

Upvotes: 8

ywbaek
ywbaek

Reputation: 3031

In addition to @user4815162342's answer,
From the documentation,

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

Notice the * between iterable and key parameter. That is the python syntax for specifying that
every parameter after * must be specified as keyword arguments.

So your custom function should be defined as the following to apply the similar implementation:

def func2(x, *, y=4, z=10):
    print(x, y, z)

func2(100, 200)

TypeError: func2() takes 1 positional argument but 2 were given

Upvotes: 8

Related Questions