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.
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.
Convert Bytes to String in Python 3
Learn how to convert bytes to str in Python 3 using decode(), text mode, and proper encodings with practical examples.