A fundamental function definition in Python requires a fixed number of parameters:
def add(x, y):
return x + y
print(add(1, 2)) # Output: 3
Here, x and y are positional parameters — you must pass exactly two arguments in order. But what happens when you need a function that can handle a varying number of arguments? This is common in many real-world scenarios, such as summing an arbitrary list of numbers.
Python solves this with two special argument types: variable positional arguments and variable keyword arguments.
Variable Positional Arguments: *args
When you prefix a parameter with a single asterisk (*), it becomes a variable positional argument. Although the conventional name is *args, you can use any valid identifier after the asterisk (e.g., *numbers). The key is the * symbol, not the name itself.
*args collects all extra positional arguments into a tuple. The function then iterates over this tuple to process the values.
Example: Summing an arbitrary count of numbers
def sum_values(*args):
total = 0
for val in args:
total += val
return total
print(sum_values(1, 3, 5)) # Output: 9
print(sum_values(2, 4, 6, 8)) # Output: 20
Here, sum_values can accept any number of positional arguments. The *args parameter bundles them into a tuple, and the loop accumulates the sum.
Variable Keyword Arguments: **kwargs
A parameter prefixed with two asterisks (**) is a variable keyword argument. By convention, this is named **kwargs. It collects all extra keyword arguments into a dictionary, where each key-value pair corresponds to a passed argument.
Example: Accepting arbitrary keyword parameters
def show_keyvals(**kwargs):
print(kwargs)
show_keyvals(a=1, b=2, c=3) # Output: {'a': 1, 'b': 2, 'c': 3}
show_keyvals(a=1, b=2, c=3, d=4) # Output: {'a': 1, 'b': 2, 'c': 3, 'd': 4}
The function receives all keyword arguments as a dictionary. You can then acces values by their keys, iterate through items, or pass them to other functions.
Combining Fixed, *args, and **kwargs
You can mix regular parameters with *args and **kwargs in a single function, as long as they appear in the correct order:
- Standard posisional parameters
*args- Standard keyword-only parameters (not shown here)
**kwargs
def total_score(base, *bonuses, **metadata):
score = base
for b in bonuses:
score += b
for key, val in metadata.items():
print(f"{key}: {val}")
return score
print(total_score(50, 10, 5, name="Alice", level="Expert"))
In this example, base is required, *bonuses picks up extra positional arguments as a tuple, and **metadata captures keyword arguments as a dictionary.
Practical Tips
- Use
*argswhen you expect a variable number of non-keyword arguments (common in decorators, logging, or mathematical functions). - Use
**kwargswhen you need to pass arbitrary named parameters (common in configuration, framework callbacks, or wrapping enother function). - The names
argsandkwargsare not enforced — you can use*fooand**bar. However, sticking to conventions improves readability.
Understanding *args and **kwargs is essential for writing flexible and reusable Python code. They allow functions to adapt to varying input without sacrificing clarity.