*args and **kwargs in Python
Mastering *args and **kwargs in Python: A Comprehensive Guide
Section titled “Mastering *args and **kwargs in Python: A Comprehensive Guide”Sometimes you do not know in advance how many arguments a function will receive — think of print(), which accepts any number of values. Python solves this with *args and **kwargs, which let a function accept an arbitrary number of positional and keyword arguments. In this guide, we’ll explore packing and unpacking, the correct argument order, and how to pass arguments between functions.
Recap: Positional and Keyword Arguments
Section titled “Recap: Positional and Keyword Arguments”Before arbitrary arguments, recall the two basic kinds:
- Positional arguments are matched by their position:
add(2, 3). - Keyword arguments are matched by name:
add(x=2, y=3).
*args and **kwargs extend these so a function can take as many as the caller passes.
*args – Arbitrary Positional Arguments
Section titled “*args – Arbitrary Positional Arguments”Putting a single * before a parameter name tells Python to pack all extra positional arguments into a tuple. By convention the parameter is named args, but any name works.
The syntax of *args in Python is as follows:
def function_name(*args):
# args is a tuple of all positional argumentsdef add_all(*args):
print("args is:", args) # a tuple
return sum(args)
print(add_all(1, 2, 3))
print(add_all(10, 20, 30, 40))Output:
C:\Users\Your Name> python args_basic.py
args is: (1, 2, 3)
6
args is: (10, 20, 30, 40)
100**kwargs – Arbitrary Keyword Arguments
Section titled “**kwargs – Arbitrary Keyword Arguments”Putting a double ** before a parameter name packs all extra keyword arguments into a dictionary. By convention it is named kwargs.
The syntax of **kwargs in Python is as follows:
def function_name(**kwargs):
# kwargs is a dict of all keyword argumentsdef build_profile(**kwargs):
print("kwargs is:", kwargs) # a dict
for key, value in kwargs.items():
print(f"{key}: {value}")
build_profile(name="Alice", age=30, city="Paris")Output:
C:\Users\Your Name> python kwargs_basic.py
kwargs is: {'name': 'Alice', 'age': 30, 'city': 'Paris'}
name: Alice
age: 30
city: ParisCombining Everything
Section titled “Combining Everything”You can mix regular parameters, *args, default parameters, and **kwargs in one function. The order is fixed:
def function(positional, *args, keyword_default=value, **kwargs):The required order is:
- Standard positional parameters
*args- Keyword-only / default parameters
**kwargs
def order(main, *extras, sauce="ketchup", **details):
print("Main:", main)
print("Extras:", extras)
print("Sauce:", sauce)
print("Details:", details)
order("Burger", "Fries", "Coke", sauce="mayo", size="large", spicy=True)Output:
C:\Users\Your Name> python combined.py
Main: Burger
Extras: ('Fries', 'Coke')
Sauce: mayo
Details: {'size': 'large', 'spicy': True}Diagram:
graph TD
A["order('Burger', 'Fries', 'Coke', sauce='mayo', size='large', spicy=True)"] --> B[main = 'Burger']
A --> C["extras = ('Fries', 'Coke')"]
A --> D[sauce = 'mayo']
A --> E["details = {size, spicy}"]
Unpacking with * and **
Section titled “Unpacking with * and **”The * and ** operators also work in the opposite direction. When calling a function, * unpacks a list/tuple into positional arguments and ** unpacks a dict into keyword arguments.
def introduce(name, age, city):
print(f"{name} is {age} and lives in {city}")
# Unpack a list into positional arguments
data = ["Bob", 25, "London"]
introduce(*data)
# Unpack a dict into keyword arguments
info = {"name": "Carol", "age": 28, "city": "Berlin"}
introduce(**info)Output:
C:\Users\Your Name> python unpacking.py
Bob is 25 and lives in London
Carol is 28 and lives in BerlinForwarding Arguments
Section titled “Forwarding Arguments”A common pattern is a wrapper function that accepts anything and passes it straight through to another function. This is how decorators wrap arbitrary functions.
def logged(func, *args, **kwargs):
print(f"Calling {func.__name__} with {args} {kwargs}")
return func(*args, **kwargs) # forward everything
def power(base, exponent):
return base ** exponent
print(logged(power, 2, exponent=10))Output:
C:\Users\Your Name> python forwarding.py
Calling power with (2,) {'exponent': 10}
1024Visualize it
Section titled “Visualize it”When a function is called, positional extras are collected into *args as a tuple, and keyword extras are collected into **kwargs as a dict.
flowchart LR
A["f(1, 2, x=3, y=4)"] --> B["1"]
A --> C["2"]
A --> D["x=3"]
A --> E["y=4"]
B --> F["*args = (1, 2)"]
C --> F
D --> G["**kwargs = {x: 3, y: 4}"]
E --> G
Conclusion
Section titled “Conclusion”*args and **kwargs let functions accept any number of arguments: *args packs extra positional arguments into a tuple, and **kwargs packs extra keyword arguments into a dictionary. The same * and ** operators unpack sequences and dictionaries back into arguments at the call site. Combine them with regular parameters in the fixed order — positional, *args, keyword defaults, **kwargs — and use them to write flexible wrappers and decorators. For more hands-on examples and in-depth tutorials, explore our resources on Python Central Hub!
Try it: *args and **kwargs Exercises
Section titled “Try it: *args and **kwargs Exercises”Exercise 1 – Collect with *args
Section titled “Exercise 1 – Collect with *args”Exercise 2 – Collect with **kwargs
Section titled “Exercise 2 – Collect with **kwargs”Exercise 3 – Unpacking at the Call Site
Section titled “Exercise 3 – Unpacking at the Call Site”pch.coffeeTagline
pch.coffeeCtapch.feedbackHeading
pch.feedbackSubheading