What is *args and **kwargs?
In Python, *args and **kwargs are special syntaxes used in function definitions to pass a variable number of arguments to a function. They provide flexibility, allowing functions to accept any number of non-keyword and keyword arguments, respectively.
*args (Non-Keyword Arguments)
The *args syntax allows a function to accept a variable number of non-keyword arguments. When used as a parameter, *args collects all positional arguments passed to the function into a tuple. The asterisk (*) unpacks an iterable (like a list or tuple) when calling a function, passing its elements as individual positional arguments.
def my_sum(*args):
result = 0
for x in args:
result += x
return result
print(my_sum(1, 2, 3))
# Output: 6
print(my_sum(10, 20, 30, 40))
# Output: 100
my_list = [5, 6, 7]
print(my_sum(*my_list))
# Output: 18
The name args is merely a convention; you could use *numbers or *items, but *args is widely accepted and recommended for readability.
**kwargs (Keyword Arguments)
The kwargs syntax allows a function to accept a variable number of keyword arguments. When used as a parameter, kwargs collects all keyword arguments passed to the function into a dictionary, where the keys are the argument names and the values are their corresponding values. The double asterisk (**) unpacks a dictionary when calling a function, passing its key-value pairs as keyword arguments.
def greet_person(**kwargs):
if 'name' in kwargs and 'greeting' in kwargs:
print(f"{kwargs['greeting']}, {kwargs['name']}!")
elif 'name' in kwargs:
print(f"Hello, {kwargs['name']}!")
else:
print("Hello there!")
greet_person(name="Alice", greeting="Hi")
# Output: Hi, Alice!
greet_person(name="Bob")
# Output: Hello, Bob!
my_dict = {'name': 'Charlie', 'age': 30}
greet_person(**my_dict)
# Output: Hello, Charlie!
Similar to *args, the name kwargs is a convention. You could use data or options, but **kwargs is the standard.
Combining *args and **kwargs
It's common to use both *args and **kwargs in the same function definition. When doing so, there's a specific order that must be followed:
- Standard positional arguments
- Standard keyword arguments
*args**kwargs
def combined_example(fixed_arg, *args, default_kwarg='default', **kwargs):
print(f"Fixed Argument: {fixed_arg}")
print(f"Positional Arguments (*args): {args}")
print(f"Default Keyword Argument: {default_kwarg}")
print(f"Keyword Arguments (**kwargs): {kwargs}")
combined_example(10, 20, 30, default_kwarg='custom', key1='value1', key2='value2')
# Output:
# Fixed Argument: 10
# Positional Arguments (*args): (20, 30)
# Default Keyword Argument: custom
# Keyword Arguments (**kwargs): {'key1': 'value1', 'key2': 'value2'}
combined_example('start', 'middle', 'end', extra=True)
# Output:
# Fixed Argument: start
# Positional Arguments (*args): ('middle', 'end')
# Default Keyword Argument: default
# Keyword Arguments (**kwargs): {'extra': True}
Key Takeaways
*argscollects an arbitrary number of non-keyword (positional) arguments into a tuple.**kwargscollects an arbitrary number of keyword arguments into a dictionary.- They enhance function flexibility, allowing them to handle varying argument lists without explicit parameter declarations.
- The unpacking operators
*and**can also be used when *calling* a function to expand iterables (for*args) or dictionaries (for**kwargs) into individual arguments.