Variable Argument Lists
Learn about Python's dynamic function argument capabilities for tasks like web page downloading and flexible configuration options.
We'll cover the following...
Overview
Default values alone do not allow us all the flexibility we might want. One thing that makes Python really slick is the ability to write methods that accept an arbitrary number of positional or keyword arguments without explicitly naming them. We can also pass arbitrary lists and dictionaries into such functions. In other languages, these are sometimes called variadic arguments, varargs.
Examples
For example, we could write a function to accept a link or list of URLs and download the web pages. The idea is to avoid the confusing-looking overhead of a singleton list when we only want one page downloaded. Instead of accepting a single value with a list of URLs, we can accept an arbitrary number of arguments, where each argument is a URL. We do this by defining one positional parameter to receive all the argument values. This parameter has to be last (among the positional parameters), and we’ll decorate it with a *
in the function definition as follows:
from urllib.parse import urlparsefrom pathlib import Pathdef get_pages(*links: str) -> None:for link in links:url = urlparse(link)name = "index.html" if url.path in ("", "/") else url.pathtarget = Path(url.netloc.replace(".", "_")) / nameprint(f"Create {target} from {link!r}")# etc.
The *
in the *links
parameter says, I’ll accept any number of arguments and put them all in a tuple named links. If we supply only one argument, it will be a list with one element; if we supply no arguments, it will be an empty list. Thus, all these function calls are valid:
from urllib.parse import urlparsefrom pathlib import Pathdef get_pages(*links: str) -> None:for link in links:url = urlparse(link)name = "index.html" if url.path in ("", "/") else url.pathtarget = Path(url.netloc.replace(".", "_")) / nameprint(f"Create {target} from {link!r}")# etc.get_pages()get_pages('https://www.archlinux.org')get_pages('https://www.archlinux.org','https://dusty.phillips.codes','https://itmaybeahack.com')
Note that our type hint suggested that all of the positional argument values are of the same type, str
, in this example. This is a widespread expectation: the variable parameters feature is little more than syntactic sugar, saving us from writing a dumb-looking list. The alternative to one type for the variable parameter tuple is potentially confusing: why write a function expecting a complex collection of distinct types, but—somehow—not state this in the parameter definitions? Don’t write that function.
We can also accept arbitrary keyword arguments. These ...