In this comprehensive article, we will delve into the intricacies of how *args and **kwargs operate, and explore the significant role they play in enhancing the flexibility and functionality of functions within the Python programming language. By understanding these powerful features, you will be better equipped to create more versatile and dynamic code, allowing you to handle a wide range of input arguments and keyword arguments with ease.
*args
*args
is a special syntax in Python that allows a function to accept a variable number of positional arguments. The term "args" is short for "arguments." When you use *args
as a parameter in a function definition, it allows the function to accept any number of positional arguments, and those arguments are collected into a tuple within the function.
Here's a basic example of how *args
works:
def my_function(*args):
for arg in args:
print(arg)
my_function(1, 2, 3, "hello")
In this example, my_function
accepts any number of positional arguments, and it prints each argument one by one. When you call my_function(1, 2, 3, "hello")
, it will print:
1
2
3
hello
Key points about *args
:
The
*args
parameter should be the last parameter in the function's parameter list. Any regular positional parameters must come before it.You can name the
*args
parameter differently, but*args
is a common convention and makes the code more readable.You can use any number of positional arguments when calling a function that uses
*args
. They will be collected into a tuple within the function.You can combine
*args
with other regular parameters. For example:def example_function(arg1, arg2, *args): # arg1 and arg2 are regular parameters # *args collects any additional positional arguments pass
You can use
*args
in functions to make them more flexible and capable of handling a variable number of arguments without explicitly specifying each argument in the function's signature.
Here's a more practical example where *args
is used to calculate the sum of a variable number of numbers:
def calculate_sum(*args):
return sum(args)
result = calculate_sum(1, 2, 3, 4, 5)
print(result) # Output: 15
In this case, calculate_sum
can accept any number of arguments, and it calculates their sum.
def func1(a, b, c):
# code
l = [10, 20, 30]
func1(*l)
In the provided example, it is not possible to pass the list 'l' directly as an argument to the function 'func1'. Instead, we must first unpack the elements of the list and then pass them individually to the function. This is achieved by using the asterisk (*) operator, which allows us to unpack the elements of the list 'l' and pass them as separate arguments to the function 'func1'.
Keyword Arguments
Recall that positional parameters can, optionally be passed as named (keyword) arguments. We can make keyword arguments mandatory. To do so, we create parameters after the positional parameters have been exhausted.
def func(a, b, *args, d):
#code
In this case, *args effectively exhausts all positional arguments and d must be passed as a keyword (named) argument.
func(1, 2, 'x', 'y', d = 100) โ a = 1, b = 2, args = ('x', 'y'), d = 100
func(1, 2, d = 100) โ a = 1, b = 2, args = (), d = 100
func(1, 2) #This is wrong d was not a keyword argument
We can even omit any mandatory positional arguments:
def func(*args, d):
#code
func(1, 2, 3, d=100) โ args = (1, 2, 3), d = 100
func(d=100) โ args = (), d = 100
In fact we can force no positional arguments at all:
def func(*, d):
#code
func(1, 2, 3, d=100) โ Exception
func(d=100) โ d = 100
* indicates the "end" of positional arguments
Putting it together
def func(a, b=1, *args, d, e=True):
# code
def func(a, b=1, *, d, e=True):
# code
a: mandatory positional argument (may be specified using a named argument)
b: optional positional argument (may be specified positionally, as a named argument, or not at all), defaults to 1
args: catch-all for any (optional) additional positional arguments
d: mandatory keyword argument
e: optional keyword argument, defaults to True
**kwargs
**kwargs
is another special syntax in Python, similar to *args
, but it is used to accept a variable number of keyword arguments in a function. The term "kwargs" is short for "keyword arguments." When you use **kwargs
as a parameter in a function definition, it allows the function to accept any number of keyword arguments, and those arguments are collected into a dictionary within the function.
Here's an example of how **kwargs
works:
def my_function(**kwargs):
for key, value in kwargs.items():
print(f"{key}: {value}")
my_function(name="Alice", age=25, city="New York")
In this example, my_function
accepts any number of keyword arguments, and it prints each argument as a key-value pair. When you call my_function(name="Alice", age=25, city="New York")
, it will print:
name: Alice
age: 25
city: New York
Key points about **kwargs
:
The
**kwargs
parameter should also be the last parameter in the function's parameter list, just like*args
. Any regular positional and keyword parameters must come before it.You can name the
**kwargs
parameter differently, but**kwargs
is a common convention and makes the code more readable.You can use any number of keyword arguments when calling a function that uses
**kwargs
. They will be collected into a dictionary within the function, with the argument names as keys and the corresponding values.You can use
**kwargs
in functions to make them more flexible and capable of handling a variable number of keyword arguments without explicitly specifying each argument in the function's signature.
Here's an example of using **kwargs
to create a function that builds a dictionary with user-defined key-value pairs:
def build_dictionary(**kwargs):
return kwargs
result = build_dictionary(name="John", age=30, city="Los Angeles")
print(result) # Output: {'name': 'John', 'age': 30, 'city': 'Los Angeles'}
In this case, build_dictionary
accepts any number of keyword arguments, and it returns a dictionary containing those arguments.
Putting it all together
positional arguments | keyword-only arguments |
*args is used to scoop up a variable amount of remaining positional arguments. The parameter name args is arbitrary โ * is the real performer here | **kwargs is used to scoop up a variable amount of remaining keyword arguments. The parameter name kwargs is arbitrary โ ** is the real performer here |
tuple | dictionary |
may have default values | may have default values |
Typical Use Case: Python's print() function
*objects arbitrary number of positional arguments after that are keyword-only arguments they all have default values, so they are all optional
In conclusion, understanding and utilizing args and *kwargs in Python functions significantly enhances their flexibility and functionality. By employing these powerful features, you can create versatile and dynamic code that can handle a wide range of input arguments and keyword arguments with ease, making your programs more adaptable and efficient.
Practice Use case:
Data Validation and Parsing: Write a function that validates and parses user input, such as a date or email address, and returns it in a structured format.
File Manipulation: Write functions to perform various file operations, such as copying, moving, or deleting files, and handling exceptions gracefully.
Password Strength Checker: Develop a function that checks the strength of a password based on criteria like length, character types, and uniqueness.
Mathematical Calculations: Create functions for solving complex mathematical problems or equations, such as finding prime factors or solving quadratic equations.