Search code examples
pythonargument-unpacking

Invalid unpacking arguments


I was reading an online document explaining unpacking (*args and **kwargs). Getting confused by the following two asserts, not sure why the second function is invalid. Could anyone help me to understand the reason?

def f(x, y, z):
    return [x, y, z]

t = (3,)  
d = {"z": 4}
assert f(2, *t, **d) == [2, 3, 4]
assert f(x=2, *t, **d) == [2, 3, 4]  # TypeError: f() got multiple values for argument 'x'

Reference https://caisbalderas.com/blog/python-function-unpacking-args-and-kwargs/


Note: This question differs from TypeError: got multiple values for argument because it requires additional knowledge of how argument unpacking works in Python.


Solution

  • You are trying to place a positional argument after a keyword argument. The actual error message is confusing. I am honestly surprised placing tuple unpacking after a keyword is allowed.

    It is the similar to doing:

    f(x=2, 3, 4)
    

    Which raises a SyntaxError.

    I believe the difference is that the tuple unpacking is handled first and shifts keyword arguments to the right. So effectively, you have this equivalency:

    f(x=2, *t, **d)
    

    is that same as

    f(*t, x=2, **d)
    

    Which is why you are getting TypeError: f() got multiple values for argument 'x'