So far, every function we’ve written has had a fixed number of parameters. A function defined with def my_func(a, b):
requires exactly two arguments, no more and no less. But many real-world problems require more flexibility.
Think about Python’s built-in print()
function. You can give it one argument (print("hello")
), or five (print(1, 2, 3, 4, 5)
), or none at all. How can we create our own functions that accept a variable number of arguments?
In this post, we’ll learn the syntax for doing just that by using a special parameter prefix: the asterisk (*
), commonly known as *args
.
The *args
Syntax
The *args
syntax in a function definition allows you to pass a variable number of positional arguments to that function. Python will collect all of these positional arguments and pack them into a tuple for you to use inside the function.
Let’s break down the name:
- The important part is the asterisk (
*
). This is what tells Python to collect the arguments. - The name
args
is a strong and widely used convention, short for “arguments.” While you could technically name it something else (like*numbers
), it is highly recommended to stick with*args
so that other Python programmers can instantly understand your code.
The basic syntax in a function definition looks like this:
def my_function(*args):
A *args
Example: A Flexible sum
Function
Let’s build a function that can sum any amount of numbers we pass to it.
def sum_all(*numbers):
"""Calculates the sum of all numbers passed as arguments."""
print(f"I received these numbers as a tuple: {numbers}")
total = 0
# Inside the function, 'numbers' is just a regular tuple
# so we can loop through it.
for number in numbers:
total += number
return total
# Let's call it with different numbers of arguments
print(f"The sum is: {sum_all(1, 2, 3)}")
print("-" * 20)
print(f"The sum is: {sum_all(10, 20, 30, 40, 50)}")
print("-" * 20)
print(f"The sum is: {sum_all()}")
(Note: We used *numbers
here instead of *args
just to show that the name is arbitrary and can be made more descriptive.)
The output demonstrates the flexibility:
I received these numbers as a tuple: (1, 2, 3)
The sum is: 6
--------------------
I received these numbers as a tuple: (10, 20, 30, 40, 50)
The sum is: 150
--------------------
I received these numbers as a tuple: ()
The sum is: 0
As you can see, *numbers
collected all the positional arguments into a tuple, which our function was then able to process.
Combining *args
with Standard Parameters
You can also use *args
in a function that has other required positional parameters, but there is one rule:
The *args
parameter must come after all the regular positional parameters.
Python will assign arguments to the regular parameters first, and then any remaining positional arguments will be collected by *args
.
def multiply_and_add(multiplier, *numbers_to_add):
"""Multiplies a total by a multiplier."""
total = 0
for number in numbers_to_add:
total += number
return total * multiplier
# The first argument (10) goes to 'multiplier'.
# The rest (1, 2, 3) are collected into the 'numbers_to_add' tuple.
result = multiply_and_add(10, 1, 2, 3) # Result will be (1+2+3) * 10 = 60
print(result)
What’s Next?
The *args
syntax is a powerful tool for creating flexible functions that can handle any number of positional inputs. It works by gathering the arguments into a tuple, which you can then easily process inside your function.
*args
is perfect for collecting a variable number of positional arguments. But what about keyword arguments? What if you want to create a function that can accept any number of named arguments that you don’t define in advance? For this, Python has a related but different syntax. In Post #102, we will learn about **kwargs
.
Author

Experienced Cloud & DevOps Engineer with hands-on experience in AWS, GCP, Terraform, Ansible, ELK, Docker, Git, GitLab, Python, PowerShell, Shell, and theoretical knowledge on Azure, Kubernetes & Jenkins. In my free time, I write blogs on ckdbtech.com