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 call f(x1, x2, *y, x3, x4)
, if y
evaluates to a sequence y1, ..., yM
, this is equivalent to a call with M+4
positional arguments x1, 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.