*args and **kwargs
Learn how to write flexible Python functions that accept any number of arguments using *args and **kwargs.
Imagine you are building a function to greet your friends. You have three friends today, but tomorrow you might have ten. Do you write a different function for each count? No — that would be exhausting!
Python gives you two special tools — *args and **kwargs — that let your functions accept as many arguments as needed, without knowing the count in advance. Once you understand them, your functions will feel like superpowers.
See it in action
— step through the idea, then dive into the details below.Functions That Take Anything
What if you want a function that works with 2 arguments today and 10 tomorrow? *args and **kwargs let your functions accept as many inputs as needed — no rewriting required.
#Collecting Positional Arguments with *args
Think of *args as a shopping bag
You do not know exactly how many items you will pick up at the store. A bag collects everything you toss in. *args is that bag for positional arguments — however many you pass, they land together in a tuple inside your function.
def add_all(*args):
print(type(args)) # it is always a tuple
total = 0
for number in args:
total += number
return total
print(add_all(1, 2)) # two numbers
print(add_all(10, 20, 30)) # three numbers
print(add_all(5, 5, 5, 5, 5)) # five numbers#Collecting Keyword Arguments with **kwargs
def show_profile(**kwargs):
print("User profile:")
for key, value in kwargs.items():
print(f" {key}: {value}")
show_profile(name="Alice", age=30, city="London")#Combining Everything — and the Required Order
You can mix all four kinds of parameters in one function. Python enforces a strict order:
- Regular positional parameters
*args- Keyword-only parameters (with defaults)
**kwargs
def make_order(restaurant, *dishes, tip=0, **extras):
print(f"Restaurant: {restaurant}")
print(f"Dishes: {dishes}")
print(f"Tip: {tip}%")
print(f"Special requests: {extras}")
make_order(
"Pasta House",
"Carbonara", "Tiramisu",
tip=15,
allergy="nuts", seat="window"
)Order matters — always!
Putting **kwargs before *args causes a SyntaxError. Python enforces the order: regular params → *args → keyword-only → **kwargs. Mix them up and your code will not even start.
#Unpacking at the Call Site
def greet(first, last, greeting="Hello"):
print(f"{greeting}, {first} {last}!")
# Unpack a list into positional args with *
name_parts = ["Jane", "Doe"]
greet(*name_parts)
# Unpack a dict into keyword args with **
options = {"first": "John", "last": "Smith", "greeting": "Hi"}
greet(**options)Unpacking is great for forwarding settings
Store your config in a dictionary, then pass it anywhere with function(**config). No need to type every key out individually — just unpack and go.
What type does Python use to store values collected by *args inside a function?
Key takeaways
- `*args` collects any number of extra positional arguments into a **tuple** inside your function.
- `**kwargs` collects any number of extra keyword arguments into a **dict** inside your function.
- Parameter order is strict: regular params → `*args` → keyword-only → `**kwargs`.
- At the call site, `*iterable` unpacks into positional arguments and `**mapping` unpacks into keyword arguments.
- These tools let you write flexible, reusable functions that handle varying inputs gracefully.
What does this code print?
def add_all(*args):
total = 0
for n in args:
total += n
return total
print(add_all(4, 6))
print(add_all(1, 2, 3))This code has a bug. What is wrong?
def show_info(**kwargs, *args):
for key, value in kwargs.items():
print(f"{key}: {value}")
for item in args:
print(item)
show_info(color="red", "apple", "banana")Complete the code so that calling greet(**options) prints "Hi, Ada!".
def greet(name, greeting): print(f"{greeting}, {name}!") options = {"name": "Ada", "greeting": "Hi"} greet(options)
Put these lines in the right order to define and call a function that prints each topping passed to it.
for topping in args:
list_toppings("cheese", "peppers", "olives")print(topping)
def list_toppings(*args):
Write a function called summarize that accepts a title (regular parameter), any number of bullet points (via args), and any number of metadata fields (via *kwargs). It should print the title on the first line, each bullet point prefixed with '- ', and then each metadata key-value pair. Test it with at least two bullet points and two keyword arguments.
Try it live — edit the code and hit Run to execute real Python: