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?
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.
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.
**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.
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.
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 callf(x1, x2, *y, x3, x4)
, ify
evaluates to a sequencey1, ..., yM
, this is equivalent to a call withM+4
positional argumentsx1, 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.
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))
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With