Here’s another article in the Functions in Python series. This time we’ll see how to pass an arbitrary number of positional parameters to functions.
If you haven’t read the previous parts yet, feel free to do so. Here they are:
6) Mutable Optional Parameters
Today we’ll learn how to pass an arbitrary number of positional parameters to a function.
In the examples so far we had no parameters or a fixed number of parameters. The number of parameters a function is passed is called its arity, so if the number of parameters is fixed, the arity is definite. But sometimes we don’t know how many parameters are needed. Let’s imagine a function which returns the sum of all the numbers passed to it as arguments multiplied by 2. It could be 5 numbers, 20 or 130, for example. One way to do it is use a sequence, like a list for example. Then we could pass a list of any length to the function like so:
def sum_double(numbers):
return sum(numbers) * 2
print(sum_double([2,3]))
print(sum_double([7,6,2,3,1,4,3,2]))
The output is:
10
56
Tuple References
A different approach, commonly used, is using tuple references. A tuple reference is a parameter prefixed with an asterisk *, which must be the last parameter passed to the function. An exception to this rule are keyword parameters, which may come after the tuple reference.
A tuple reference just tells the function that any number of parameters may be passed to the function in its place. We could rewrite our sum_double function like so:
def sum_double(*numbers):
return sum(numbers) * 2
Now we can pass any number of parameters, not just one list:
print(sum_double(2,3))
print(sum_double(7,6,2,3,1,4,3,2))
And the output is identical as before.
As said before, the arguments are in a tuple, so if we pass no arguments to the function, we get an empty tuple. Here’s a simple function that can take an arbitrary number of arguments. We’ll use it with 0 arguments and then with 3:
>>> def echo_words(*words):
... print(words)
...
>>> echo_words()
()
>>> echo_words("one", "two", "three")
('one', 'two', 'three')
Here’s another example, with more parameters:
def multigreeter(fancy, *names):
if fancy:
greeting = "Hello my dear and beloved {}!"
else:
greeting = "Hi {}!"
for name in names:
print(greeting.format(name))
multigreeter(False, "John", "Mary")
This function has one regular parameter, fancy, and a tuple reference. This means, that after fancy we can pass any number of names. In our example we passed 2 names and we set fancy to False, thus choosing a pretty simple greeting for each name. Here’s the output:
Hi John!
Hi Mary!
And now let’s set fancy to True and use more names in the function call:
multigreeter(True, "John", "Mary", "Monica", "Louis", "Santiago", "Barbie")
The output is:
Hello my dear and beloved John!
Hello my dear and beloved Mary!
Hello my dear and beloved Monica!
Hello my dear and beloved Louis!
Hello my dear and beloved Santiago!
Hello my dear and beloved Barbie!
List Unpacking
Suppose we have a list of names. Could we pass it to our multigreeter function? Let’s try:
friends = ["Mary", "Monica", "Louis"]
multigreeter(True, friends)
Here’s what we get:
Hello my dear and beloved ['Mary', 'Monica', 'Louis']!
Not necessarily what we hoped for. There’s an easy way to do it. We just have to unpack the list, which can be done with the asterisk * like so:
multigreeter(True, *friends)
Now the result is:
Hello my dear and beloved Mary!
Hello my dear and beloved Monica!
Hello my dear and beloved Louis!
Tuple Reference Followed by Keyword Arguments
One more example. As said before, we may use keyword arguments after the tuple reference. Here’s an example:
def join_words(*words, separator):
return separator.join(words)
print(join_words("one", "two", "three", "four", separator = " and "))
print(join_words("one", "two", "three", "four", separator = "*"))
And here’s the output:
one and two and three and four
one*two*three*four