The functions you have seen before mostly had positional arguments. When calling functions, we substitute the values according to the position of the argument names in the function definition.
If you call a function with the arguments (10, 20)
, where:
- The argument
x
will get10
- The argument
y
will get20
There is a code example:
def add(x, y):
return x + y
Variable numbers of arguments
Using positional arguments looks simple. It is as close as you can get to using functions in mathematics, and it is convenient until you need to implement them to take any number of arguments.
As you will recall, the print
function can take as many arguments as you want to pass to it. It does work if you call it without arguments at all.
So how do we teach our function to take many arguments? We need some special syntax:
def f(*args):
print(type(args))
print(args)
f()
# => tuple
# => ()
f(1, 'a', None, False)
# => tuple
# => (1, 'a', None, False)
Here we see the function header — the line that describes the function name and its arguments. We write one args
argument but put an asterisk before it.
The asterisk means this variable will receive all arguments in tuples from the current position to the end. We can see that there can be only one greedy argument that will devour everything. It can be only at the end of the argument list. The following arguments will not get values otherwise.
We can use another example to show that *args
is starved for arguments, while ordinary ones are always mandatory. Let us look at a more complicated example:
def greet(name, *args):
for n in (name,) + args:
print(f'Hello, {n}!')
greet('Tom', 'Ann')
# => Hello, Tom!
# => Hello, Ann!
greet()
# TypeError: `greet()` missing 1 required positional argument: 'name'
The function accepts multiple arguments, but we should pass at least one argument. This first argument will be the value of the name
variable, and the rest will be in *args
. Similarly, you can do any number of required arguments.
Passing arguments as collections
Sometimes you may want to form a set of arguments and pass them to the function.
For example, you might want to read arguments from a file or get them programmatically in some other way. Again, we need an asterisk:
names = ['Tom', 'Ann']
greet(*names)
# => Hello, Tom!
# => Hello, Ann!
Moreover, we can pass some of the arguments directly. You do not always need to substitute collections one at a time:
…
greet(
'Bob', *['Mary', 'Clair'], 'Sam',
*('Henry', 'John')
)
# => Hello, Bob!
# => Hello, Mary!
# => Hello, Clair!
# => Hello, Sam!
# => Hello, Henry!
# => Hello, John!
By the way, Pythonists call the mentioned argument *args
, so try to adhere to this convention.
Are there any more questions? Ask them in the Discussion section.
The Hexlet support team or other students will answer you.
For full access to the course you need a professional subscription.
A professional subscription will give you full access to all Hexlet courses, projects and lifetime access to the theory of lessons learned. You can cancel your subscription at any time.