2
def f(a,*b):
    print(a,b)

for the function f defined as above, if I call f(1, *(2,3)) it prints 1, (2,3) as expected.

However calling f(a=1, *(2,3)) causes an error: TypeError: f() got multiple values for argument 'a'

Any positional argument can also be supplied as an explicit keyword argument. There should be only one interpretation for f(a=1, *(2,3)) without ambiguity.

Royalblue
  • 639
  • 10
  • 22
  • 1
    [The docs](https://docs.python.org/3/reference/expressions.html#calls) explain this: "First, a list of unfilled slots is created for the formal parameters. If there are N positional arguments, they are placed in the first N slots. Next, for each keyword argument, the identifier is used to determine the corresponding slot (if the identifier is the same as the first formal parameter name, the first slot is used, and so on). If the slot is already filled, a TypeError exception is raised." – Amadan Sep 03 '18 at 05:33
  • @Amadan, thanks for the link. Actually I was reading "Learning Python 5ed" and I think(found) what's mentioned in the book is contradicting to the python doc. – Royalblue Sep 03 '18 at 09:33

1 Answers1

1
def f(a,*b):
    print(a,b)
f(1,*(2,3))
f(1,2,3)

consider the example above both will call the same function in the same way now if you specify a =1

f(a=1,2,3)
#or in other syntax
f(2,3,a=1)

then it has an ambiguity to whether to consider a=1 or a=2 since 2 is the first positional argument and a=1 is an explicit keyword argument .

Albin Paul
  • 3,330
  • 2
  • 14
  • 30
  • Thank you Albin for the explanation. The below sentences from the python doc is the key to understanding the behavior: "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." as you explained. What's explained in "Learning Python 5e" (p531) seems not accurate because it says the step "Assign keyword arguments by matching names" is followed by "Assign extra nonkeyword arguments to *name tuple", which are a=1 and *(2,3) respectively in my question. – Royalblue Sep 03 '18 at 09:34