How to use an Undefined Number of Arguments in Python using *args and **kwargs
Python offers flexibility when it comes to handling function arguments. Two powerful features, *args
and **kwargs
, provide a way to work with a variable number of arguments in a function. In this blog, we'll explore these concepts, understand their applications, and see how they contribute to the versatility of Python functions.
In this article, we will cover what ** (double star/asterisk) and * (star/asterisk) do for parameters in Python—allowing us to pass an undefined number of arguments to a function.
Special Symbols Used for passing arguments in Python:
*args
(Non-Keyword Arguments)**kwargs
(Keyword Arguments)
Understanding *args (Arbitrary Arguments)
The term *args
may initially seem mysterious, but it is a straightforward concept. In Python, *args
allows a function to accept any number of positional arguments. The asterisk (*) symbol before the argument name is a signal to gather all the positional arguments into a tuple.
def example_function(*args):
for arg in args:
print(arg)
example_function(1, 2, 3, 'four')
In this example, example_function
takes any number of arguments and prints each one. When called with four arguments, it outputs:
1
2
3
four
The flexibility of *args
becomes apparent when you want a function to handle an unpredictable number of inputs without explicitly specifying each parameter.
Unpacking Lists and *args
*args
is not limited to function definitions; it can also be used for unpacking elements from a list or tuple into individual arguments when calling a function.
def sum_values(a, b, c):
return a + b + c
values = [1, 2, 3]
result = sum_values(*values)
print(result)
In this case, *values
unpacks the list into individual arguments, resulting in the equivalent of sum_values(1, 2, 3)
.
Understanding **kwargs (Key Word Arguments)
While *args
deals with positional arguments, **kwargs
is designed for handling keyword arguments. The double asterisk (**) signals that the function can accept any number of keyword arguments, gathering them into a dictionary.
def example_function(**kwargs):
for key, value in kwargs.items():
print(f"{key}: {value}")
example_function(name='John', age=25, city='Example City')
Executing this function with keyword arguments produces the following output:
name: John
age: 25
city: Example City
Combining *args and **kwargs
The true power of these features shines when they are used together in a function signature. This allows the function to accept both positional and keyword arguments, providing unparalleled flexibility.
def flexible_function(*args, **kwargs):
print("Positional arguments:")
for arg in args:
print(arg)
print("\nKeyword arguments:")
for key, value in kwargs.items():
print(f"{key}: {value}")
flexible_function(1, 2, 3, name='John', age=25)
In this example, flexible_function
gracefully handles a mix of positional and keyword arguments. This can be incredibly useful in situations where you want to create versatile and adaptable functions, and can be especially useful when paired with decorators ands wrapper functions.
Conclusion
In the world of Python, *args
and **kwargs
are designed for flexibility and can be utilized to make easily adaptable functions. Whether you're dealing with an uncertain number of inputs or striving for a more adaptable function interface, these features empower you to write code that is both concise and versatile. Embrace the simplicity of *args
and the expressiveness of **kwargs
to make your Python functions more robust and accommodating to various use cases.