Table of Contents
What Will You Learn
In this tutorial, you'll learn how Python's *args
and **kwargs
enable you to write functions that accept a dynamic number of arguments. You'll explore how to use them effectively, the difference between positional and keyword arguments, and real-world use cases. By the end, you'll write more flexible, reusable, and professional-looking Python code.
As a beginner in Python, you’ll quickly notice that functions vary in how they receive input. Sometimes, the number of arguments is unknown or flexible — and that’s exactly where
*args
becomes essential. Understanding *args
equips you with the ability to write functions that accept any number of positional arguments. This makes
your code more dynamic, reusable, and scalable.
You’ll find *args
used in many standard libraries, decorators, and frameworks. It allows functions to remain clean while still being adaptable to future changes.
Whether you're working with APIs, data pipelines, or utility functions — mastering *args
is a foundational skill that will make your code more professional and
future-proof. Learning it early builds your confidence in handling real-world coding challenges.
What Does *args
Mean in Python?
In Python, *args
allows you to pass a variable number of positional arguments to a function. The asterisk (*
) collects all additional unnamed arguments
into a single tuple named args
. This enables your function to accept zero, one, or many arguments without modifying the function signature. It’s especially useful
when you don’t know how many inputs a user or external module might provide.
By convention, the name args
is commonly used, but any valid variable name will work after the asterisk. You can loop over args
inside the function to
process each value. It is important to note that *args
must be placed after all regular positional parameters. If used with **kwargs
(keyword
arguments), *args
should appear first in the function definition. While it may look simple, *args
is a powerful pattern that helps you write more
flexible and generalized code.
How to Split *args
in Python?
You can "split" *args
by accessing individual elements of the tuple inside the function. Since *args
collects all extra positional arguments into a
tuple, you can index it, slice it, or loop through it like any other sequence. This gives you full control over the contents and lets you process arguments selectively. It's
especially helpful when the first few arguments have specific meanings, and the rest can be grouped together.
def process_data(*args):
first = args[0]
others = args[1:]
print("First:", first)
print("Others:", others)
process_data(10, 20, 30, 40)
# Output: First: 10 / Others: (20, 30, 40)
How to Pass *args
in Python?
To pass *args
to a function, prepend the argument list with an asterisk when calling the function. This unpacks the values and passes them as separate positional
arguments. It’s useful when you already have a tuple or list of values and want to pass them to a function that accepts multiple parameters. This approach keeps the code clean
and dynamic.
def greet(name, age):
print(f"{name} is {age} years old.")
data = ("Alice", 30)
greet(*data)
# Output: Alice is 30 years old.
How to Unpack *args
in Python?
Unpacking *args
means extracting individual values from a tuple of arguments passed to a function. You can use the asterisk *
during assignment or
within a function signature. This technique is helpful when you want to distribute values into multiple variables or when forwarding arguments to another function. Python handles
this unpacking intuitively.
# Unpack into variables
def demo_unpack(*args):
a, b, *rest = args
print("a:", a)
print("b:", b)
print("rest:", rest)
demo_unpack(1, 2, 3, 4, 5)
# Output: a: 1 / b: 2 / rest: [3, 4, 5]
How to Use *args
in Python
Using *args
allows your function to accept any number of positional arguments as a tuple. You define it in the function signature by adding an asterisk before a
parameter name, commonly *args
. Inside the function, you can loop over args
, access it with indexing, or apply operations to all arguments. This makes
the function more flexible and suitable for unknown input lengths. It’s particularly useful in decorators, helper functions, and mathematical utilities.
Keep in mind that
*args
must appear after standard positional parameters and before**kwargs
if both are used.
What Are Some Practical Examples of Using *args
in Python?
*args
is commonly used in scenarios where input length may vary or when you want to keep a function flexible and concise. It is ideal for mathematical operations,
formatting utilities, or when building wrapper functions. You will often see it in frameworks, decorators, and utility toolkits. The ability to accept multiple arguments without
defining each one makes code reusable and cleaner. Below are real-world uses for *args
in Python:
- Summing numbers: Pass any number of values and return the total.
- Joining strings: Concatenate multiple string values into one output.
- Flexible logging: Print logs with any number of values using a single log function.
- Mathematical operations: Write calculators that accept a dynamic number of inputs.
- Command-line utilities: Handle varying user inputs passed to a function.
- Frameworks and decorators: Pass unknown arguments to wrapped or inner functions.
- UI functions: Dynamically pass layout or styling arguments to GUI elements.
What Are the Differences Between *args
and **kwargs
in Python?
*args
and **kwargs
are used to pass a variable number of arguments to a function, but they serve different purposes. *args
collects extra
positional arguments as a tuple, while **kwargs
collects extra keyword arguments as a dictionary. This means *args
is used when you don’t know how many
positional arguments you’ll receive, and **kwargs
is used when you don’t know how many named arguments will be passed. They can be used together in the same
function, but *args
must come first in the parameter list. You can also combine them with standard parameters for flexible function definitions. They are useful for
decorators, API wrappers, GUI development, and extensible utility functions. Using them correctly makes your code clean, reusable, and future-proof.
Feature | *args | **kwargs |
Type collected | Tuple of values | Dictionary of key-value pairs |
Used for | Positional arguments | Keyword arguments |
Unpacking syntax | * |
** |
Typical usage | Math operations, utilities | Configuration, styling, options |
Data structure | Tuple | Dict |
Call style | func(1, 2, 3) |
func(a=1, b=2) |
Order in definition | Must appear before **kwargs |
Must appear after *args |
Common Beginner Mistakes
Passing Keyword Arguments to *args
A common mistake is trying to pass keyword arguments to a function that only accepts *args
. Since *args
only collects positional values, any
keyword-based input will result in a TypeError
. To fix this, either add **kwargs
to the function signature or avoid passing named arguments. Always
match the function’s parameter style when calling it.
# Incorrect
def show_values(*args):
print(args)
show_values(a=1, b=2) # TypeError
# Correct
def show_values(**kwargs):
print(kwargs)
Forgetting to Unpack *args
When Passing
Beginners often forget to unpack a list or tuple using *
when passing it to a function that expects separate arguments. As a result, the function receives the entire
list as a single item instead of individual elements. Use *
before the variable to expand it during the function call. This ensures each item is passed as a separate
argument.
# Incorrect
def add(a, b):
return a + b
nums = [2, 3]
add(nums) # TypeError
# Correct
add(*nums) # Output: 5
Using *args
Without Any Parameters
Another mistake is defining *args
in a function and not using it. While syntactically valid, this adds confusion and suggests that the function accepts more
arguments than it actually uses. If you don’t intend to process extra arguments, remove *args
from the definition to make the code clearer and easier to maintain.
# Unnecessary
def greet(name, *args):
print(f"Hello, {name}") # args not used
# Better
def greet(name):
print(f"Hello, {name}")
Incorrect Parameter Order
When using *args
along with other parameters, putting them in the wrong order causes syntax errors. In Python, *args
must come after regular positional
arguments and before **kwargs
. Always follow the correct sequence: regular parameters → *args
→ **kwargs
. This ensures your function is
defined and called properly.
# Incorrect
def func(*args, x, y): # SyntaxError
# Correct
def func(x, y, *args):
pass
Modifying *args
Directly
*args
is a tuple, which is immutable. Trying to append or modify its contents directly will raise an error. If you need to manipulate the arguments, first convert
args
to a list. This allows you to add, remove, or update items without errors.
# Incorrect
def update_args(*args):
args.append(5) # AttributeError
# Correct
def update_args(*args):
args_list = list(args)
args_list.append(5)
Frequently Asked Questions
What are *args
and **kwargs
in Python functions?
In Python, *args
and **kwargs
allow you to define functions that accept a flexible number of arguments. *args
is used to collect extra
positional arguments into a tuple. You can loop through args
or access its items using indexes. On the other hand, **kwargs
collects keyword arguments
into a dictionary. This is useful when you want to allow optional, named parameters in your function.
For example:
def example(*args, **kwargs):
print(args)
print(kwargs)
example(1, 2, name="Alice", active=True)
# Output: (1, 2)
# {'name': 'Alice', 'active': True}
These features are commonly used in APIs, decorators, wrappers, and dynamic function calls.
Can I use *args
and normal parameters together?
Yes, you can use *args
alongside regular parameters in the same function. Just make sure to place regular parameters before *args
in the function
definition. The standard order is: positional parameters → *args
→ default parameters → **kwargs
. This structure allows you to handle both required
and variable-length inputs in a clean and predictable way.
For example:
def report(title, *items):
print("Report:", title)
for item in items:
print("-", item)
report("To-Do List", "Task 1", "Task 2", "Task 3")
In this setup, title
is required, and any number of additional tasks can follow.
How do I forward *args
to another function?
You can forward *args
from one function to another by using the unpacking operator (*
) when calling the next function. This is particularly useful
when writing wrapper functions, decorators, or middleware that extend existing functionality without modifying the inner function’s signature. The same pattern applies to
**kwargs
using double asterisks (**
).
Example:
def log(*args):
print("LOG:", *args)
def wrapper(*args):
log(*args)
wrapper("File saved", 200, "OK")
# Output: LOG: File saved 200 OK
This technique helps you create flexible and reusable function structures.
What happens if I don’t use the unpacking operator with *args
?
If you pass a list or tuple to a function expecting multiple arguments and forget to unpack it using the *
operator, Python treats the list as a single positional
argument. This often results in a TypeError
if the function was expecting individual arguments. Always use *
to unpack the elements when passing them
into a function expecting multiple inputs.
For example:
def multiply(a, b):
return a * b
pair = (4, 5)
# Incorrect:
# multiply(pair) → TypeError
# Correct:
multiply(*pair) # Output: 20
This ensures each element is passed to the correct parameter position.
Are there limits to how many arguments I can pass using *args
?
Technically, there is no predefined limit in Python on how many arguments you can pass using *args
. However, practical limitations exist depending on memory and
stack size. Passing hundreds or thousands of arguments is rarely useful and can lead to code that is difficult to maintain or debug. In such cases, it’s better to pass a list
or other data structure instead of relying on *args
.
Keep in mind that functions with flexible signatures are powerful but should still follow clean design principles. Use *args
when you truly need flexibility — not
as a way to avoid thinking about your inputs.