There is one extra subtlety with function arguments (which is beyond what many novice
programmers would need to know, so feel free to skip this section). In a function
definition, Python has the ability to specify arbitrary anonymous arguments at the end of
the list of ordinary arguments. It uses a special syntax for these extra arguments, which
can be confusing when you first see it. Consider the following illustrative function:
def testFunc(item, *args, **kw):
print('Mandatory argument:', item)
print('Unnamed arguments:', args)
print('Keyword dictionary:', kw)
Here we have one mandatory argument, item, and at the end there are two special
arguments, *args (short hand for ‘arguments’) and **kw (short hand for ‘keywords’)
which collect any number of extra arguments that may be passed in. The asterisks (*) have
to be used as shown; one for args and two for kw, but the actual argument names can be
different. When the function is called with more arguments than just a single item value,
these extra arguments are placed inside the args and kw variables. Simple listed
arguments, i.e. those that do not use the name=value syntax, are put in the args tuple and
those that do use the name=value syntax are put in the kw dictionary, with the keys being
the argument names and the values being what these are mapped to. Inside the function
args and kw are used without the asterisks (except possibly when passed into another
function). Note that in a function definition you don’t have to collect both kinds of
arbitrary arguments; you can have *args without **kw or vice versa.
The following examples illustrate how using this arbitrary argument syntax adds a large
degree of flexibility to function calls, although this is sometimes at the expense of
reducing clarity.
testFunc('Hello', 1, 99, valueA="abc", valueB=7.0)
Here the variable item is set to the value ‘Hello’, the variable args is set to the tuple (1,
99) and the variable kw is set to the dictionary {‘valueA’:“abc”, ‘valueB’:7.0}.
testFunc('Hello', valueA="abc", valueA=7.0)
Here args is empty and kw is set to the dictionary {‘valueA’:“abc”, ‘valueB’:7.0}.
testFunc('Hello')
Here only the mandatory item is specified; args and kw are both empty.
You may be thinking why you would ever want to have anonymous arguments in a
function. Indeed, in general they are often avoided, because it means it is not particularly
obvious what the arguments are expected to be. However, there are some situations where
the use of anonymous arguments does make sense. For example, you may have a function
whose input arguments are dictated by some other consideration, e.g. it might be a
function which will be called by an application that someone else wrote, and which you
can’t change, but where the arguments are not needed to make the function work. In that
case one might write the function definition as follows, to indicate that the only argument
that matters is the first one:
def myPublicFunc(item, *irrelevantArgs, **irrelevantKw):
print('Ignoring all arguments except', item)
Also, you sometimes have a function that passes forward most of its information to
another function without using it directly, and that second function may have lots of
arguments. Rather than listing all the arguments in the first function, it is quite common to
collect anonymous arguments and just pass them all onto the second function. So, for
example, suppose there is a function, setStyle, that a draw function calls to set lots of
things like the colour, line style, shading etc. The draw function might then be defined as
follows, passing the anonymous arguments to another function that is called inside:
def draw(points, *args, **kw):
# some code
setStyle(*args, **kw)
# some more code
This would work if the definition of setStyle accepts anonymous arguments like
def setStyle(*args, **kw):
or named arguments
def setStyle(fgColor="red", bgColor="black", line):
Consider the following call to the draw function:
draw(points, bgColor="green")
In the first case where setStyle accepts anonymous arguments the kw dictionary is set to
{‘bgColor’: “green”}, and the args tuple is empty. In the second case where there are
named arguments bgColor is ‘green’ but the other arguments have default values; i.e.
fgColor is ‘red’ and linestyle is ‘plain’.
When calling functions with anonymous arguments the asterisk syntax should be used
with care, given that
setStyle(*args, **kw)
is different to
setStyle(args, kw)
In the former the function can have any number of unspecified arguments which are
filled in by the elements of the tuple and the dictionary. For the latter the function would
be expecting exactly two arguments; here the first argument is a tuple and the second a
dictionary.
Lasty, the anonymous arguments notation is sometimes convenient if the number of
arguments being passed into a function is large. You can define the argument tuple and
keyword argument dictionary before the function call, thus reducing clutter:
tupleArgs = (value1, value2, value3)
dictKw = {'color':'blue', 'depth':3, 'gamma':0.271728}
myFunction(*tupleArgs, **dictKw)