Question
Python *args and **kwargs Explained in Function Parameters
Question
In Python, what do *args and **kwargs mean when they appear in function definitions like these?
def foo(x, y, *args):
pass
def bar(x, y, **kwargs):
pass
I want to understand what the single asterisk (*) and double asterisk (**) do for parameters in a function definition, and how they affect the values a function can accept.
Short Answer
By the end of this page, you will understand how *args collects extra positional arguments, how **kwargs collects extra keyword arguments, when to use each one, and how they fit into real Python function design.
Concept
In Python function definitions, *args and **kwargs let a function accept a flexible number of arguments.
*argscollects extra positional arguments into a tuple.**kwargscollects extra keyword arguments into a dictionary.
This is useful when you do not know in advance exactly how many arguments will be passed to a function, or when you want to forward arguments to another function.
For example:
def foo(x, y, *args):
print(x)
print(y)
print(args)
foo(1, 2, 3, 4, 5)
Output:
1
2
(3, 4, 5)
Here:
xgets1ygets
Mental Model
Think of a function like a bag-check desk at an airport.
- Regular parameters like
xandyare for bags with fixed labels. *argsis a large bin for any extra unlabeled bags.**kwargsis a separate bin for extra bags with labels attached.
So if a function knows it always needs two required values, but might receive more:
- the extra unnamed values go into
*args - the extra named values go into
**kwargs
Another way to think about it:
*args= "collect leftover positional items"**kwargs= "collect leftover named items"
This makes functions more flexible without forcing you to define every possible parameter up front.
Syntax and Examples
Basic syntax
def func(required1, required2, *args, **kwargs):
print(required1)
print(required2)
print(args)
print(kwargs)
Example with *args
def add_numbers(*args):
return sum(args)
print(add_numbers(1, 2, 3))
print(add_numbers(10, 20, 30, 40))
Output:
6
100
Explanation:
- All positional arguments are collected into the tuple
args sum(args)works becauseargsbehaves like a normal tuple of numbers
Example with
Step by Step Execution
Consider this code:
def show(a, b, *args, **kwargs):
print("a:", a)
print("b:", b)
print("args:", args)
print("kwargs:", kwargs)
show(1, 2, 3, 4, color="blue", size="M")
Step 1: Match required positional parameters
Python assigns the first positional argument to a:
a = 1
Then the second positional argument to b:
b = 2
Step 2: Collect remaining positional arguments into args
The remaining positional arguments are 3 and 4.
So:
args = (3, 4)
Real World Use Cases
1. Wrapper functions
You may write a function that adds logging before calling another function.
def logged_call(func, *args, **kwargs):
print(f"Calling {func.__name__}")
return func(*args, **kwargs)
This lets the wrapper accept any arguments the wrapped function needs.
2. Framework and library APIs
Many frameworks accept optional settings through keyword arguments.
def connect(host, port, **options):
print(host, port, options)
This allows new options to be added later without changing every call.
3. Building utility functions
A function might need to accept any number of values.
def average(*numbers):
return sum(numbers) / len(numbers)
4. Passing configuration data
Keyword arguments are useful for configuration-like input.
():
{
: username,
: profile
}
Real Codebase Usage
In real projects, developers use *args and **kwargs carefully, not everywhere.
Common patterns
Forwarding arguments
A function may pass received arguments to another function.
def save_with_log(*args, **kwargs):
print("Saving data...")
return save(*args, **kwargs)
This is common in wrappers, adapters, and decorators.
Optional extension points
Libraries sometimes use **kwargs to allow extra options without breaking older code.
def send_email(to, subject, **options):
timeout = options.get("timeout", 30)
retry = options.get("retry", False)
Validation
Good code often validates values inside kwargs.
def create_product(name, **kwargs):
allowed = {, , }
unknown = (kwargs) - allowed
unknown:
TypeError()
Common Mistakes
1. Thinking args and kwargs are special names
They are just conventional names.
def test(*values, **options):
print(values)
print(options)
The special part is the * and **.
2. Forgetting the data types they create
*argsbecomes a tuple**kwargsbecomes a dictionary
Broken expectation:
def bad(*args):
args.append(5) # tuples do not have append
Fix:
def good(*args):
values = list(args)
values.append(5)
return values
3. Using without checking valid keys
Comparisons
| Concept | What it collects | Resulting type | Example |
|---|---|---|---|
| Regular parameter | One specific argument | Any value | def f(x): |
*args | Extra positional arguments | tuple | def f(*args): |
**kwargs | Extra keyword arguments | dict | def f(**kwargs): |
*args vs **kwargs
Cheat Sheet
# Collect extra positional arguments
def func(*args):
print(args) # tuple
# Collect extra keyword arguments
def func(**kwargs):
print(kwargs) # dict
# Use both
def func(a, b, *args, **kwargs):
pass
Rules
*argscollects leftover positional arguments**kwargscollects leftover keyword argumentsargsandkwargsare naming conventions, not keywords*argsis a tuple**kwargsis a dictionary- Use them when the number or names of inputs may vary
Example
def demo(x, *args, **kwargs):
print(x)
print(args)
(kwargs)
demo(, , , color=)
FAQ
What does *args mean in Python?
*args means a function can accept any number of extra positional arguments. Inside the function, they are stored as a tuple.
What does **kwargs mean in Python?
**kwargs means a function can accept any number of extra keyword arguments. Inside the function, they are stored as a dictionary.
Are args and kwargs special Python keywords?
No. They are just common names. The special meaning comes from * and ** in the function definition.
Can I use both *args and **kwargs in the same function?
Yes. This is very common in wrappers and decorators.
When should I use *args?
Use *args when a function should accept a variable number of positional values, such as many numbers to sum.
When should I use **kwargs?
Use **kwargs when a function should accept optional named settings or when forwarding options to another function.
Mini Project
Description
Build a small Python utility function that records events with a required event name, any number of extra positional tags, and any number of keyword details. This demonstrates how *args and **kwargs can be used together in a realistic logging-style function.
Goal
Create a function that accepts fixed parameters plus flexible extra data, then prints the collected information in a clear format.
Requirements
- Create a function named
log_eventthat requires one parameter calledevent_name - Allow the function to accept any number of extra positional arguments as tags
- Allow the function to accept any number of keyword arguments as details
- Print the event name, the tags, and the details in a readable way
- Call the function with at least two different examples
Keep learning
Related questions
@staticmethod vs @classmethod in Python Explained
Learn the difference between @staticmethod and @classmethod in Python with clear examples, use cases, mistakes, and a mini project.
Call a Function by Name in a Python Module
Learn how to call a function by name in a Python module using strings, getattr, and safe patterns for dynamic function dispatch.
Catch Multiple Exceptions in One except Block in Python
Learn how to catch multiple exceptions in one Python except block using tuples, with examples, mistakes, and real-world usage.