4 minutes
Keyword and Positional Only Arguments in Python
My flights are now synonymous with new articles… It is a welcomed distraction from the subtle armrest war, the crammed chairs with barely any leg room and the crying babies…
Here’s a small feature I recently learned about that might significantly impact your code readability: Forcing functions to take Keyword-Only Arguments or Positional Only Arguments!.
The Keyword-Only argument feature was not so recently introduced in PEP 3102. But as with most things, I’m discovering this a little bit too late 🤦♂
What this allows us to do is force a bunch of arguments to be passed by keyword only as opposed to positional arguments.
Quick Recap
In python, there are two ways to pass arguments to a function. Either by explicitly naming them, or by arranging arguments in a specific position.
We will be using the following function for our example:
def show_person(name: str, age: int, hobbies: List[str]):
return f"""The Person is {name}, he is {age} years old and has the following hobbies: {hobbies}"""
Keyword Argument
show_person(name="Fares", age=24, hobbies=["Skiing","Drinking"])
Positional Argument
show_person("Fares", 24, ["Skiing","Drinking"])
Mix of Both
We can also start with positional arguments and end with keyword arguments:
show_person("Fares", 24, hobbies=["Skiing","Drinking"])
By default, the flavor of function calling is left to the discretion of the person calling the function.
Forcing Behaviors
There is however a way to force callers to pass some/all arguments as keyword only (or as of python 3.8, as positional arguments only).
Forcing Keyword Only
To force users to use keyword only arguments for either all or some of the arguments, simply add a *
before the arguments. Anything after the *
will be keyword only.
def show_person(*, name: str, age: int, hobbies: List[str]):
return f"""The Person is {name}, he is {age} years old and has the following hobbies: {hobbies}"""
show_person(name="Fares", age=24, hobbies=["Skiing"])
## "The Person is Fares, he is 24 years old and has the following hobbies: ['Skiing']"
And what happens if we pass positional arguments?
show_person("Fares", 24, ["Skiing"])
## Traceback (most recent call last):
## File "<stdin>", line 1, in <module>
## TypeError: show_person() takes 0 positional arguments but 3 were given
Another example of keyword only function is:
def show_person(name: str, age: int, *, hobbies: List[str]):
return f"""The Person is {name}, he is {age} years old and has the following hobbies: {hobbies}"""
In the above example, both name and age are allowed to be passed by either keyword or positional arguments, but hobbies is required to be a keyword argument.
Forcing Positional Only (as of Python 3.8)
This functionality is relatively new and was introduced in Python 3.8.
The same way we can force users to call a function by only passing keyword arguments, we can also force users to call a function by only passing positional arguments.
This is done through the /
sign in the function. Anything before that sign is required to be passed as a positional only argument. Here’s an example:
def show_person(name: str, age: int, /, hobbies: List[str]):
return f"""The Person is {name}, he is {age} years old and has the following hobbies: {hobbies}"""
In that case, when calling the function, name
and age
have to be passed in positional argument only otherwise an error is returned:
show_person("Fares", 24, hobbies=["Skiing"])
Forcing Both
We could also require that users call a function with specific arguments in positional and the rest in keyword.
def show_person(name: str, /, *, age: int, /, hobbies: List[str]):
return f"""The Person is {name}, he is {age} years old and has the following hobbies: {hobbies}"""
In this case, name
can only be passed as positional while age
and hobbies
can only be passed in keyword arguments.
My Two Cents
While I see an immense benefit to using keyword only argument to improve readability, I cannot say the same thing about positional only arguments.
The only usage I see is when a function takes an obvious value and a clear name for the parameter is not so easy to come up with. But then again, some might say this is an indication that you’ve done something wrong in the design of your function 😛.
If You Must Remember Two Things
- To require users to call a function with
keyword-only
arguments, add a*
before those arguments. - To require users to call a function with
positional-only
arguments, add a/
after those arguments.