Blog Post #101: Taking a Variable Number of Arguments with *args

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

Debjeet Bhowmik

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

Leave a Comment