A function or a method can accept both positional and keyword arguments and that’s you who decide whether a function/method will accept positional or keyword argument.
You can choose what is best for your function either positional or keyword parameters according to the requirement.
In this article, you’ll learn what are the best practices for positional and keyword arguments.
Positional & Keyword Arguments
Positional arguments are passed positionally in the function/method call while the keyword or named arguments are passed by the parameter’s name along with the corresponding values.
1 2 3 |
# Positional and Keyword Args def func(p1, p2, p3): print(p1, p2, p3) |
In this example, the function func()
takes three arguments (p1
, p2
, and p3
) and prints them. This function does not explicitly state how the parameters should be passed when you call it.
Consider the following function calls that are all valid.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
# Option 1 func("Here", "we", "go") # Option 2 func("Here", "we", p3="go") # Option 3 func(p1="Here", p2="we", p3="go") # Option 4 func("Here", p2="we", p3="go") -------------------- Here we go Here we go Here we go Here we go |
Well, this looks fine that you have the flexibility to pass arguments as you wish until you are following the correct way.
Stick to the Rule
You need to stick to the rule when passing a combination of positional and keyword arguments.
The following function call will result in an error as it violates the syntax set by Python.
1 |
func("Here", p2="we", "go") |
The p1
and p3
are passed positionally while the p2
is passed as a keyword argument.
1 2 3 4 |
... func("Here", p2="we", "go") ^ SyntaxError: positional argument follows keyword argument |
You can see that this program raised a SyntaxError
stating that the positional argument cannot be passed after the keyword argument.
When you pass the keyword argument to a function, all subsequent arguments must also be passed as keywords. Positional arguments should always come before keyword arguments.
Restrict Arguments to be Positional-only and Keyword-only
One of the best practices is to bound the arguments to be positional-only and keyword-only.
You can create a function that accepts simply positional arguments, keyword arguments, or a combination of the two.
Here’s how you can achieve it.
1 2 3 4 5 6 7 8 9 10 11 |
# Takes Positional-only Args def func1(p1, p2, p3, /): print(p1, p2, p3) # Takes Keyword-only Args def func2(*, kw1, kw2, kw3): print(kw1, kw2, kw3) # Takes Mix Args def func3(pos, /, pos_kw, *, kw): print(pos, p_kw, kw) |
In this example, the function func1()
allows only positional arguments due to the slash (/
) at the end of the function definition, likewise, the function func2()
allows only keyword arguments because of the asterisk (*
) at the beginning.
But, the function func3()
accepts mixed arguments because pos
is positional-only, pos_kw
can be positional or keyword, and kw
is keyword-only.
Read – Why Slash and Asterisk Used in Function Definition?
1 2 3 4 5 6 7 8 9 10 11 |
# Passed positional-only args func1("positional", "only", "arguments") # Passed keyword-only args func2(kw1="keyword", kw2="only", kw3="arguments") # Passed mixed args func3("mixed", "arguments", kw="passed") -------------------- positional only arguments keyword only arguments mixed arguments passed |
This approach can be useful when developing an API and you don’t want users to pass values through the parameter name. In that situation, you can configure the API to only accept positional values, and you can modify the parameter name in the future without breaking anything.
Also, if you’re writing a function for e-commerce, you can utilise keyword-only parameters to avoid confusion between price, item, and so on.
Optional Arguments/Arguments with Default Value
You can set a default value for an argument if you need to by assigning a value to the parameter in the function definition.
1 2 3 4 5 |
# Function with an optional param def optional_param(name, age, height=170): print(f"Name : {name}") print(f"Age : {age}") print(f"Height: {height}") |
The function optional_param()
has a height
parameter set to a default value of 170
. If you don’t pass it in a function call, Python will assign that default value. This means that it became an optional argument.
1 2 3 4 5 |
optional_param("John", 32) -------------------- Name : John Age : 32 Height: 170 |
You can override the default value by specifying a different value. This can be helpful when you want to set a minimum or a maximum limit.
Variadic Arguments
When you’re unsure or don’t want to specify a big list of parameters in a function definition, make it accept a variadic (any number of arguments) argument instead.
1 2 3 4 5 |
# Takes any no. of args def send_invitation(*args): print("Invitation sent to:") for everyone in args: print(everyone) |
You can pass any number of positional arguments to the function send_invitation()
due to *args
. This *args
expression indicates that the function can accept any number of arguments and the values are stored in a tuple.
1 2 3 4 5 6 7 8 9 10 |
send_invitation( "John", "Max", "Cindy" ) -------------------- Invitation sent to: John Max Cindy |
Likewise, you can make a function accept variadic keyword arguments using **kwargs
.
1 2 3 4 5 6 7 8 9 10 11 |
# Takes any no. of keyword args def party_items(**kwargs): print("Party items:") for key, value in kwargs.items(): print(f"{key}: {value}") party_items( Poppers=3, Ballons=120, Sparkles=10 ) |
The **kwargs
stores keyword arguments as the key/value pair in a dictionary, so you can perform any related operations on the keys and values.
Read – Understanding *args and **kwargs in Python.
Argument Ordering
Arguments must be passed in the same order as the parameters appear in the function definition.
1 2 3 4 5 6 |
def details(name, age, occupation): print(f"Name : {name}") print(f"Age : {age}") print(f"Occupation: {occupation}") details(32, "John", "Writer") |
When you run this code, you’ll get the name
as 32
and the age
as John
due to a messed up argument order when the function is called.
1 2 3 |
Name : 32 Age : John Occupation: Writer |
But if you pass the values using the parameter name in any order, you’ll get the desired result.
1 2 3 4 5 |
details(age=32, name="John", occupation="Writer") -------------------- Name : John Age : 32 Occupation: Writer |
This is not the ideal approach because each function will differ; for example, you may create functions that accept only positional or keyword arguments.
So, the bottom line is to always pass the arguments in order as the parameters appear in the function definition.
Argument Type Hinting
It’s not a terrible idea to specify what argument type should be given when invoking the function. This will indicate that the specified type of argument should be passed.
1 2 3 4 |
# Type hinting def func(arg1: int, arg2: float): print(f"{arg1} type: {type(arg1)}") print(f"{arg2} type: {type(arg2)}") |
When you call the function func()
, arg1
should be passed as an integer and arg2
should be passed as a decimal number. This is called type hinting.
1 2 3 4 |
func(2, 3.9) -------------------- 2 type: <class 'int'> 3.9 type: <class 'float'> |
It’s not like you must pass those specified types of arguments, you can pass any type as you wish, and Python won’t throw an error because the interpreter completely ignores the type hints.
1 2 3 4 |
func("2", 3.9) -------------------- 2 type: <class 'str'> 3.9 type: <class 'float'> |
Python is a dynamically typed language, so type hints won’t be very useful but in some cases, they can be helpful to avoid bugs.
Naming the Arguments Properly
You must name your parameters in a way that defines their purpose. Let’s say you are creating a program for a vehicle company, so you must name your parameters according to that for better readability.
Conclusion
Python provides a lot of freedom to developers. Each programming language is distinct and different, and following best practices elevates them even further.
A developer should understand how to get the most out of the programming language, including how to leverage their experience and best practices.
In this article, you’ve learned some of the best practices for positional and keyword arguments that are as follows:
- Sticking to the proper syntax for passing the positional and keyword arguments
- Making the function accept only positional or keyword arguments or mixed arguments
- Setting a default value for the argument
- If you are unsure how many arguments should a function accept, use variadic arguments (
*args
and**kwargs
) in that case. - Arguments should be correctly placed to avoid unpredictable behaviour.
- Can use type hints to avoid bugs
- Name the parameters in a way that defines their purpose
πOther articles you might be interested in if you liked this one
β Understanding args and kwargs in Python: Best Practices and Guide
β Why Slash and Asterisk Used in Function Definition?
β Create a WebSocket Server and Client in Python.
β Decorators in Python and How to Create a Custom Decorator?
β Understanding the Different Uses of the Asterisk(*) in Python?
β The map() Function in Python for Mapping a Function to Each Item in the Iterable?
That’s all for now
Keep Codingββ