We frequently use functions and methods with asterisk or star characters (*
) in their definitions, as shown in the following code snippet:
def spam(*args, **kwargs):
...
Programmers unfamiliar with Python are often puzzled when they encounter this for the first time. What does the single and double asterisk/star character do?
We'll start with *args
. The single *
character tells Python that the function takes a variable number (zero or more) of positional parameters.
>>> def countargs(*args): ... print 'Passed in', len(args), 'args.' >>> countargs('a', 'b', 'c') Passed in 3 args. >>> countargs() Passed in 0 args.
You can combine normal positional parameters and *args
to require some arguments. The os.path.join
method, for example, requires at least one positional argument. Its signature is os.path.join(a, *p)
.
>>> import os >>> os.path.join('a', 'b', 'c') 'a\\b\\c' >>> os.path.join('a') 'a' >>> os.path.join() Traceback (most recent call last): TypeError: join() takes at least 1 argument (0 given)
In the last call to os.path.join
, we did not supply any arguments, so a TypeError
was raised.
You can also use the *
character when calling a function to expand a sequence (such as a list or tuple) into positional arguments. This does not require the function being called has a *args
parameter. It can be used to expand to any positional arguments. For example, if we use the countargs
function defined previously with a list of values, we will get two very different results depending on whether we use a *
to expand the list when countargs
is called.
>>> items = ['a', 'b', 'c'] >>> countargs(items) Passed in 1 args. >>> countargs(*items) Passed in 3 args.
The first call to countargs
would be equivalent to countargs(['a', 'b', 'c'])
. It passes the list as the only argument. The second call would be equivalent to countargs('a', 'b', 'c')
. It passes each item in the list as a separate positional argument.
The **kwargs
parameter is basically the same as *args
, but for keyword instead of positional parameters. The **
characters tell Python a function takes a variable number of keyword parameters.
>>> def countkwargs(**kwargs): ... print 'Passed in', len(kwargs), 'kwargs.' >>> countkwargs(a=1, b=2) Passed in 2 kwargs. >>> countkwargs() Passed in 0 kwargs.
Just like you can specify both required and variable positional parameters (as we saw in os.path.join
), you can specify regular keyword parameters along with using **kwargs
.
>>> def countkwargs2(strfunc=None, **kwargs): ... msg = 'Passed in %s kwargs.' % len(kwargs) ... if strfunc: ... msg = strfunc(msg) ... print msg >>> countkwargs2(strfunc=str.upper, a=1) PASSED IN 1 KWARGS. >>> countkwargs2(str.lower, a=1, b=2) passed in 2 kwargs.
As the second call to countkwargs2
shows, you can still use normal keyword arguments by either position or name.
And finally, you can use **
to expand a mapping, such as a dictionary, into keyword arguments that are passed into a function:
>>> mapping = dict(a=1, b=2, strfunc=str.upper) >>> countkwargs2(arg=mapping) Passed in 1 kwargs. >>> countkwargs2(**mapping) PASSED IN 2 KWARGS.
The *args
and **kwargs
parameters are important features of Python with many useful applications, just a fraction of which are presented in this book. They allow a level of dynamic programming that would otherwise be extremely difficult.
As a final note, the names args
and kwargs
are convention only. You can just as well name them *spam
and **eggs
.