Why does python only allow named arguments to follow a tuple unpacking expression in a function call?
>>> def f(a,b,c): ... print a, b, c ... >>> f(*(1,2),3) File "<stdin>", line 1 SyntaxError: only named arguments may follow *expression
Is it simply an aesthetic choice, or are there cases where allowing this would lead to some ambiguities?
Python offers a very powerful tuple assignment tool that maps right hand side arguments into left hand side arguments. THis act of mapping together is known as unpacking of a tuple of values into a norml variable. WHereas in packing, we put values into a regular tuple by means of regular assignment.
Unpacking a Tuple Note: The number of variables must match the number of values in the tuple, if not, you must use an asterisk to collect the remaining values as a list.
Tuple packing refers to assigning multiple values into a tuple. Tuple unpacking refers to assigning a tuple into multiple variables. You have already used tuple packing because it is as simple as: >>> django_movie = ("Tarantino", 2012, 8.4, "Waltz & DiCaprio")
In Python, unpacking is not limited to tuples only. You can unpack a list or a string with the same syntax. Unpacking is more commonly known as multiple assignment, as it reminds of assigning multiple variables on the same line.
i am pretty sure that the reason people "naturally" don't like this is because it makes the meaning of later arguments ambiguous, depending on the length of the interpolated series:
def dangerbaby(a, b, *c): hug(a) kill(b) >>> dangerbaby('puppy', 'bug') killed bug >>> cuddles = ['puppy'] >>> dangerbaby(*cuddles, 'bug') killed bug >>> cuddles.append('kitten') >>> dangerbaby(*cuddles, 'bug') killed kitten
you cannot tell from just looking at the last two calls to dangerbaby
which one works as expected and which one kills little kitten fluffykins.
of course, some of this uncertainty is also present when interpolating at the end. but the confusion is constrained to the interpolated sequence - it doesn't affect other arguments, like bug
.
[i made a quick search to see if i could find anything official. it seems that the * prefix for varags was introduced in python 0.9.8. the previous syntax is discussed here and the rules for how it worked were rather complex. since the addition of extra arguments "had to" happen at the end when there was no * marker it seems like that simply carried over. finally there's a mention here of a long discussion on argument lists that was not by email.]
I suspect that it's for consistency with the star notation in function definitions, which is after all the model for the star notation in function calls.
In the following definition, the parameter *c
will slurp all subsequent non-keyword arguments, so obviously when f
is called, the only way to pass a value for d
will be as a keyword argument.
def f(a, b, *c, d=1): print "slurped", len(c)
(Such "keyword-only parameters" are only supported in Python 3. In Python 2 there is no way to assign values after a starred argument, so the above is illegal.)
So, in a function definition the starred argument must follow all ordinary positional arguments. What you observed is that the same rule has been extended to function calls. This way, the star syntax is consistent for function declarations and function calls.
Another parallelism is that you can only have one (single-)starred argument in a function call. The following is illegal, though one could easily imagine it being allowed.
f(*(1,2), *(3,4))
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