Sign in to your Python Morsels account to save your screencast settings.
Don't have an account yet? Sign up here.
Let's define a function that accepts a keyword-only 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.
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
print
function works this wayThis 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.
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'
You'll actually sometimes see this *
thing on its own within the Python standard library.
For example in the chown
function in the os
module (used for changing the ownership of a file) uses 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.
*
in a function definitionSo, 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).
Need to fill-in gaps in your Python skills?
Sign up for my Python newsletter where I share one of my favorite Python tips every week.
Python, like many programming languages, has functions. A function is a block of code you can call to run that code.
Python's functions have a lot of "wait I didn't know that" features. Functions can define default argument values, functions can be called with keyword arguments, and functions can be written to accept any number of arguments.
To track your progress on this Python Morsels topic trail, sign in or sign up.
Need to fill-in gaps in your Python skills? I send weekly emails designed to do just that.