Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python 3.5 TypeError: got multiple values for argument [duplicate]

def f(a, b, *args):
    return (a, b, args)

f(a=3, b=5)  
(3, 5, ())

whereas:

f(a=3, b=5, *[1,2,3])  
TypeError: got multiple values for argument 'b'

Why it behaves like this?
Any particular reason?

like image 525
Jan Sikora Avatar asked Jul 07 '16 14:07

Jan Sikora


People also ask

Where () takes 2 positional arguments but 3 were given?

The Python "TypeError: takes 2 positional arguments but 3 were given" occurs for multiple reasons: Forgetting to specify the self argument in a class method. Forgetting to specify a third argument in a function's definition. Passing three arguments to a function that only takes two.

What is positional argument?

Positional arguments are arguments that need to be included in the proper position or order. The first positional argument always needs to be listed first when the function is called. The second positional argument needs to be listed second and the third positional argument listed third, etc.

How does Kwargs work?

**kwargs works just like *args , but instead of accepting positional arguments it accepts keyword (or named) arguments. Take the following example: # concatenate.py def concatenate(**kwargs): result = "" # Iterating over the Python kwargs dictionary for arg in kwargs.

What are positional and keyword arguments in python?

A positional argument means its position matters in a function call. A keyword argument is a function argument with a name label. Passing arguments as keyword arguments means order does not matter.


2 Answers

In the documentation for calls:

If the syntax *expression appears in the function call, expression must evaluate to an iterable. Elements from these iterables are treated as if they were additional positional arguments. For the call f(x1, x2, *y, x3, x4), if y evaluates to a sequence y1, ..., yM, this is equivalent to a call with M+4 positional arguments x1, x2, y1, ..., yM, x3, x4.

And, this is followed by:

A consequence of this is that although the *expression syntax may appear after explicit keyword arguments, it is processed before the keyword arguments (and any **expression arguments – see below).

(emphasis mine)

So Python will first process the *args as positional arguments, assign a value to b and re-assign it with b=5 resulting in an error for the keyword argument having multiple values.

like image 170
Dimitris Fasarakis Hilliard Avatar answered Sep 21 '22 19:09

Dimitris Fasarakis Hilliard


The problem is the keywords. You are not allowed positional arguments after keyword arguments.

f(3, 5, *[1,2,3])

works fine, in that it passes a tuple with the values 1,2,3. The same as:

f(3, 5, *(1,2,3))

Keywords must always come after positional arguments, so it is your function declaration which is incorrect:

def f(*args, a, b):
    return (a, b, args)

print(f(a=3, b=5))
print(f(*[1,2,3], a=3, b=5))

Gives:

(3, 5, ())
(3, 5, (1, 2, 3))
like image 34
cdarke Avatar answered Sep 20 '22 19:09

cdarke