The setup
Let's say I have a function:
def variadic(*args, **kwargs):
print("Positional:", args)
print("Keyword:", kwargs)
Just for experiment's sake, I call it with the following:
variadic({'a':5, 'b':'x'}, *{'a':4, 'b':'y'}, **{'a':3, 'b':'z'})
Output:
Positional: ({'a': 5, 'b': 'x'}, 'a', 'b')
Keyword: {'a': 3, 'b': 'z'}
The problem
I don't have an issue with the keyword arguments.
For the positional ones, however, we get the tuple ({'a': 5, 'b': 'x'}, 'a', 'b')
. I understand why we get the first element ({'a': 5, 'b': 'x'}
), but I am surprised that we are getting only the keys (a
, b
) from {'a':4, 'b':'y'}
. I don't understand why this is happening. I think I expected an error from passing a dictionary to *args
instead.
Possible answers?
I have not been able to find an answer, but suspect that when parsing *args
Python does something along the lines:
for arg in args:
do something
and since we passed a dictionary, and iterating over a dictionary like this (as opposed to d.items()
) gives us only the keys, we just get the keys. Can anyone confirm that or clear up why this is happening?
CodePudding user response:
In a function call, an argument prefixed with a *
must be an iterable value. Each value produced by iterating over the argument is provided to the function as a separate positional argument. (Note that this is independent of a paraemter prefixed with a *
, which collects positional arguments not assigned to any other parameter into a tuple.)
Values of type dict
are iterable; the iterator for a dict
yields the keys of the dict
.