Last updated: Apr 8, 2024
Reading time·5 min
The Python "SyntaxError: positional argument follows keyword argument" occurs when we pass keyword arguments before positional ones in a call to a function.
To solve the error, pass positional arguments in the right order and pass any keyword arguments after the positional ones.
Here is an example of how the error occurs.
def get_employee(first, last, salary): return {'first': first, 'last': last, 'salary': salary} # ⛔️ SyntaxError: positional argument follows keyword argument get_employee('Bobby', last='Hadz', 100)
Passing a positional argument to a function looks like 'Bobby',
, whereas
passing a keyword argument to a function looks like last='Hadz'
.
'Bobby'
.first = 'Bobby'
.last
, and then provided a value for the salary
positional argument.If you specify keyword arguments before positional ones, Python has no way of knowing a value for which positional argument is provided.
Instead, the keyword arguments must come after the positional ones.
def get_employee(first, last, salary): return {'first': first, 'last': last, 'salary': salary} # ✅ Keyword arguments come after positional ones result = get_employee('Bobby', last='Hadz', salary=100) # 👇️ {'first': 'Bobby', 'last': 'Hadz', 'salary': 100} print(result)
We passed first
as a positional argument and last
and salary
as keyword
arguments to resolve the issue.
One way to solve the error is to only pass positional arguments to the function.
def get_employee(first, last, salary): return {'first': first, 'last': last, 'salary': salary} # ✅ Only passing positional arguments to the function result = get_employee('Bobby', 'Hadz', 100) print(result) # 👉️ {'first': 'Bobby', 'last': 'Hadz', 'salary': 100}
The example above only uses positional arguments. The function knows for which parameter we passed a value based on the order of the positional arguments.
Alternatively, you can only pass keyword arguments to the function.
def get_employee(first, last, salary): return {'first': first, 'last': last, 'salary': salary} result = get_employee(salary=100, first='Alice', last='Smith') print(result) # 👉️ {'first': 'Bobby', 'last': 'Hadz', 'salary': 100}
salary=100
.You can also pass positional and keyword arguments in the same function call. Note that keyword arguments must follow positional ones.
def get_employee(first, last, salary): return {'first': first, 'last': last, 'salary': salary} result = get_employee('Bobby', salary=100, last='Hadz') print(result) # 👉️ {'first': 'Bobby', 'last': 'Hadz', 'salary': 100}
We used a positional argument (Bobby
) and 2 keyword arguments - (salary=100
and last='Hadz'
).
Make sure that any positional arguments you specify in the function call are passed in the correct order (the order must correspond to the parameter list in the function's definition).
Make sure that you aren't just blindly moving the keyword arguments after all of the positional ones because the order of the positional arguments matters.
Here is an example of how this can go wrong.
def get_employee(first, last, salary): return {'first': first, 'last': last, 'salary': salary} # ⛔️ TypeError: get_employee() got multiple values for argument 'last' result = get_employee('Bobby', 100, last='Hadz')
The keyword argument in the example comes after any positional ones, but we still got an error.
first
and last
parameters and then passed a value for the last
parameter using a keyword argument.The easiest way to solve the error in the example is to pass only positional arguments (in the correct order) to the function.
def get_employee(first, last, salary): return {'first': first, 'last': last, 'salary': salary} # ✅ Only passing positional arguments (in the correct order) result = get_employee('Bobby', 'Hadz', 100) # 👇️ {'first': 'Bobby', 'last': 'Hadz', 'salary': 100} print(result)
A function's parameters must be defined in the following order:
*args
- receives excess positional arguments.**kwargs
- receives excess keyword arguments.*args
and **kwrags
in a function's definitionYou might also see the *args
and **kwargs
syntax being used to receive
excess positional or keyword arguments in a function.
def get_employee(first, salary, last='Doe', *args, **kwargs): print(args) # 👉️ ('developer', ) print(kwargs) # 👉️ {'country': 'Belgium'} return {'first': first, 'last': last, 'salary': salary} emp_1 = get_employee( 'Bobby', 100, 'Hadz', 'developer', country='Belgium' ) # 👇️ {'first': 'Bobby', 'last': 'Hadz', 'salary': 100} print(emp_1)
The form *identifier
is initialized to a tuple that receives any excess
positional arguments.
The form **identifier
is initialized to an ordered mapping that receives any
excess keyword arguments.
An excess positional argument with the value of developer
was supplied to the
function, so it got added to the args
tuple.
Similarly, the function doesn't define a country
argument, so it got added to
the **kwargs
dictionary.
We passed the value developer
as a positional argument and the
country='Belgium'
value as a keyword argument.
emp_1 = get_employee( 'Bobby', 100, 'Hadz', 'developer', country='Belgium' )
Note that the keyword argument comes after all positional ones.
You can also only use **kwargs
or *args
, depending on your use case.
Here is an example function that only takes excess keyword arguments.
def get_employee(first, salary, last='Doe', **kwargs): # 👇️ {'country': 'Belgium', 'city': 'Example'} print(kwargs) return {'first': first, 'last': last, 'salary': salary} emp_1 = get_employee( 'Bobby', 100, country='Belgium', city='Example' ) # 👇️ {'first': 'Bobby', 'last': 'Doe', 'salary': 100} print(emp_1)
The function doesn't define the country
and city
arguments, so they got
added to the kwargs
dictionary.
The same is the case when a function definition has default parameters - it has to define its default parameters after the positional ones.
# 👇️ default parameter `last='Doe'` def get_employee(first, salary, last='Doe'): return {'first': first, 'last': last, 'salary': salary} # 👇️ not passing value for default parameter emp_1 = get_employee('Bobby', 100) print(emp_1) # {'first': 'Bobby', 'last': 'Doe', 'salary': 100} # 👇️ passing value for default parameter emp_2 = get_employee('Alice', 100, 'Smith') print(emp_2) # {'first': 'Alice', 'last': 'Smith', 'salary': 100}
Default parameter values have the form parameter = expression
.
Positional parameters cannot follow a parameter with a default value because otherwise, Python has no way of knowing if we passed an argument for the default parameter or for a positional one.
You can learn more about the related topics by checking out the following tutorials: