Related article:
- Keyword (Named) Arguments in Python: How to Use Them
- Asterisks in Python: what they are and how to use them
- Positional vs Keyword Arguments
- Accepting any number of arguments to a function
Transcript:
Let's define a function that accepts a keyword-only argument.
Accepting Multiple Positional Argument
This greet
function accepts any number of positional arguments:
>>> def greet(*names):
... for name in names:
... print("Hello", name)
...
If we give it some names, it's going to print out Hello
, and then the name, for each of those names:
>>> greet("Trey", "Jo", "Ian")
Hello Trey
Hello Jo
Hello Ian
It does this through the *
operator, which is capturing all the positional arguments given to this function.
Positional and Keyword-Only Argument
If we wanted to allow the greeting (Hello
) to be customized we could accept a greeting
argument:
>>> def greet(*names, greeting):
... for name in names:
... print(greeting, name)
...
We might try to call this new greet
function like this:
>>> greet("Trey", "Hi")
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: greet() missing 1 required keyword-only argument: 'greeting'
But that gives us an error. The error says that greet
is missing one required keyword-only argument greeting
.
That error is saying is that greeting
is a required argument because it doesn't have a default value and it must be specified as a keyword argument when we call this function.
So if we want to customize greeting
, we can pass it in as a keyword argument:
>>> greet("Trey", greeting="Hi")
Hi Trey
>>> greet("Trey", greeting="Hello")
Hello Trey
We probably want greeting
to actually have a default value of Hello
. We can do that by specifying a default value for the greeting
argument:
>>> def greet(*names, greeting="Hello"):
... for name in names:
... print(greeting, name)
...
>>> greet("Trey", "Jo")
Hello Trey
Hello Jo
Because greeting
is after that *names
in our function definition, Python sees greeting
as a keyword-only argument: an argument that can only be provided as a keyword argument when this function is called.
It can only be given by its name like this:
>>> greet("Trey", "Jo", greeting="Hi")
Hi Trey
Hi Jo
Keyword-Only Arguments in Built-in Functions
This is actually something you'll see in some of Python's built-in functions. For example, the print
function accepts any number of positional arguments, as well as four optional keyword-only arguments: sep
, end
, file
, and flush
:
>>> help(print)
Help on built-in function print in module builtins:
print(...)
print(value, ..., sep=' ', end='\n', file=sys.stdout, flush=False)
Note that the documentation for print
doesn't use the *
syntax, but that ...
is print
's way of indicating that it accepts any number of values and then all of the arguments after that must be keyword arguments.
If we look at the documentation for greet
, you'll see how keyword-only arguments usually show up in documentation:
>>> help(greet)
Help on function greet in module __main__:
greet(*names, greeting='Hello')
Everything after that *
(greeting
in this case), can only be specified as a keyword argument.
Keyword-Only Arguments without Capturing All Positional Arguments
It is also possible to make a function that doesn't capture any number of positional arguments, but does have some keyword-only arguments. The syntax for this is really weird.
Let's make a multiply
function that accepts x
and y
arguments:
>>> def multiply(*, x, y):
... return x * y
...
That lone *
before x
and y
means that they must be specified as keyword arguments.
So, if we were to try to call multiply
with two positional arguments, we'll get an error:
>>> multiply(1, 2)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: multiply() takes 0 positional arguments but 2 were given
To call this function, we have to specify x
and y
as keyword arguments:
>>> multiply(x=1, y=2)
2
If we call this function with nothing you'll see an error message similar to what we saw before about required keyword-only arguments:
>>> multiply()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: multiply() missing 2 required keyword-only arguments: 'x' and 'y'
Keyword-Only Arguments in the Standard Library
You'll actually sometimes see this *
thing on its own within the Python standard library. For example in thechown
function in the os
module (used for changing the ownership of a file) uses the a lone *
to specify keyword-only arguments:
chown(path, uid, gid, *, dir_fd=None, follow_symlinks=True)
Change the owner and group id of path to the numeric uid and gid.
The chown
function documentation shows path
, uid
, gid
, and then a *
(which isn't an argument itself), and then dir_fd
and follow_symlinks
. That lone *
is a way of noting that everything after that point is a keyword-only argument.
The last two arguments, dir_fd
and follow_symlinks
can only be specified by their name when the chown
function is called.
Summary
So, whenever you see a function that uses *
to capture any number of positional arguments (e.g. *args
in the function definition), note that any arguments defined after that *
capturing can only be specified as a keyword argument (they're keyword-only arguments).
Also if you see a function that has an *
on its own with a comma after it, that means that every argument after that point, is a keyword only argument it must be specified by its name when that function is called.
from Planet Python
via read more
No comments:
Post a Comment