Variable Arguments (*args)
Learn to accept any number of arguments with *args.
The *args syntax allows functions to accept any number of positional arguments, making them flexible for varying numbers of inputs without defining each parameter explicitly.
π Concepts & Theory
*args allows a function to accept any number of positional arguments. The asterisk (*) unpacks arguments into a tuple.
**Basic *args Syntax:**
def function_name(*args):
# args is a tuple of all arguments
for arg in args:
print(arg)
Simple Example:
def print_all(*args):
for item in args:
print(item)
print_all(1, 2, 3) # 3 arguments
print_all("a", "b") # 2 arguments
print_all(1) # 1 argument
print_all() # 0 arguments (empty tuple)
Sum Any Number of Numbers:
def sum_all(*numbers):
total = 0
for num in numbers:
total += num
return total
print(sum_all(1, 2, 3)) # 6
print(sum_all(10, 20, 30, 40)) # 100
**Using Built-in Functions on *args:**
def find_max(*numbers):
return max(numbers)
def calculate_average(*numbers):
return sum(numbers) / len(numbers)
**Mixing Regular Parameters with *args:**
def greet_all(greeting, *names):
for name in names:
print(f"{greeting}, {name}!")
greet_all("Hello", "Alice", "Bob", "Charlie")
# Hello, Alice!
# Hello, Bob!
# Hello, Charlie!
**Rules for *args:**
- *args must come after regular parameters
- Only one *args per function
- *args captures remaining positional arguments
- *args is a tuple (immutable)
# β
Correct order
def func(a, b, *args):
pass
# β Wrong - *args must be after regular params
def func(*args, a, b):
pass
Parameter Order:
def full_example(required, *args, keyword_only, kwargs):
pass
# Call:
full_example(1, 2, 3, keyword_only=4, extra=5)
# required = 1
# args = (2, 3)
# keyword_only = 4
# kwargs = {'extra': 5}
Common Use Cases:
1. Print Function:**
def custom_print(*values, sep=" "):
print(sep.join(str(v) for v in values))
custom_print(1, 2, 3, sep="-") # "1-2-3"
2. Mathematical Operations:
def multiply_all(*numbers):
result = 1
for num in numbers:
result *= num
return result
3. List Builder:
def make_list(*items):
return list(items)
my_list = make_list(1, 2, 3, 4, 5)
Unpacking Arguments:
def add(a, b, c):
return a + b + c
numbers = [1, 2, 3]
result = add(*numbers) # Unpacks list into arguments
# Same as: add(1, 2, 3)
Type Checking:
def sum_numbers(*args):
for arg in args:
if not isinstance(arg, (int, float)):
raise TypeError(f"Expected number, got {type(arg)}")
return sum(args)
Best Practices:
- Use descriptive names:
*values,*numbers,*items - Document expected types
- Consider if *args is really needed (might be better to pass a list)
- Don't overuse - explicit parameters are often clearer
π― Your Challenge
Create a function multiply_all(*numbers) that multiplies all arguments together and returns the product.
π Starter Code
def multiply_all(*numbers):
pass
- Use *numbers to accept any number of arguments
- Initialize a result variable to 1 (not 0!)
- Loop through each number in numbers
- Multiply each number with the result
- Return the final result
Solution
def multiply_all(*numbers):
result = 1
for num in numbers:
result *= num
return result
Explanation
This function demonstrates *args for accepting variable numbers of arguments. The * before numbers tells Python to collect all positional arguments into a tuple named numbers. We initialize result to 1 (multiplicative identity), then iterate through each number in the tuple, multiplying it with the running result. Calling multiply_all(2, 3, 4) creates numbers = (2, 3, 4), and the function computes 1 * 2 * 3 * 4 = 24. The function works with any number of arguments: multiply_all(5) returns 5, multiply_all(2, 3) returns 6, etc. Starting with 1 is crucialβstarting with 0 would always return 0.
β οΈ Common Mistakes to Avoid
- Initializing result to 0 instead of 1
- Forgetting the * in the parameter definition
- Trying to modify the args tuple (it's immutable)
- Not handling the case of zero arguments (returns 1)
- Using += instead of *= for multiplication