Declaring functions

You should hopefully already be familiar with how Python uses simple functions. This tutorial looks at more advanced ways to declare function parameters.

A simple function

Here is a simple Python function declaration, that we will extend in this article:

def fancy_print(s):
    out = '[' + s + ']'
    print(out)

This is simple enough, the function takes one parameter, and whatever value you pass in gets printed out with enclosing square brackets.

Here is how we would call it:

fancy_print('Hello')

The result would be:

[Hello]

Optional parameters

Suppose we wanted to extend our function so that instead of enclosing our output string in square brackets, we could choose what symbols to use. That is fairly easy to do:

def fancy_print(s, before, after):
    out = before + s + after
    print(out)

fancy_print('Hello', '<', '>')   # Prints '<Hello>'

This is good, but what is we usually want to use square brackets, and only use different brackets quite rarely. In that case we can use optional parameters (sometimes called defaulted parameters), like this:

def fancy_print(s, before='[', after=']'):
    out = before + s + after
    print(out)

The function now has one mandatory parameter, s, and two optional parameters, before and after. We only need to supply the optional parameters if we don’t want to use the default values. Here are some examples:

fancy_print('Hello')             # Prints '[Hello]'
fancy_print('Hello', '(')        # Prints '(Hello]'
fancy_print('Hello', '<', '>')   # Prints '<Hello>'

In this case:

Recipe for optional parameters

In a function declaration, the optional parameters must be placed after the non-optional parameters.

This is simply to avoid confusion. For example, suppose you were allowed to declare a function like this:

def fancy_print(before='[', after=']', s):

This declaration is actually a syntax error, which makes sense if you think about it. The behaviour if you call this function with 1 or 2 parameters would be quite unclear - should the optional parameters take the values (leaving s undefined) or should s be assigned (breaking the order of the parameters)?

Variable number of parameters

Some Python functions, for example the print functions can accept any number of parameters. You can pass in as many values as you like and it will print them all:

print(1, 'xyz', 9)    # prints 1 xyz 9

How would you go about creating a function like this? Here is how we could make a multiple parameter version of fancy_print:

def multi_print(*args):
    for s in args:
        out = '[' + s + ']'
        print(out)

multi_print('abc', 'defgh', 'XYZ')

Notice that the *args parameter has an asterisk in front of it. This identifies it as a variable length argument list. Although it is often given the name *args, you can give it any valid name, of course.

What this parameter does is collect all the parameters passed in, and place them in a tuple. Inside the body of the function, you can access the tuple of values via the args variable.

Our code loops over the tuple, and prints:

[abc]
[defgh]
[XYZ]

It is valid to call multi_print with no parameters. The tuple will be empty, and nothing will be printed.

Mixing parameter types

You can mix fixed and variable parameters in a function. For example we could add a title to our multi_print function:

def multi_print(title, *args):
    print(title)
    print('--------')
    for s in args:
        out = '[' + s + ']'
        print(out)

multi_print('My list', 'abc', 'defgh', 'XYZ')

Here, title picks up the first parameter value, and args gets any remaining parameters as a tuple. The function must be called with at least one parameter, because title needs a value. Here is what it prints:

My list
--------
[abc]
[defgh]
[XYZ]

You can also add defaulted parameters. Here we will add back the before and after parameters from the original code above:

def multi_print(title, *args, before='[', after=']'):
    print(title)
    print('--------')
    for s in args:
        out = before + s + after
        print(out)

multi_print('My list', 'abc', 'defgh', 'XYZ', before='<', after='>')

This prints:

My list
--------
<abc>
<defgh>
<XYZ>

Keyword arguments

Keyword arguments are a bit like variable argument lists, but they work with named parameters. The are declared like this:

def some_function(**kwargs):

The form **kwargs identifies it as a keyword argument list (it doesn’t have to be called kwargs of course). It is called like this:

some_function(name='count', value=1):

This allows you to pass in named parameters that some_function doesn’t even know about until it is called. The parameters are stored in a dictionary, accessed by the variable kwargs. Here is a simple function that uses this:

def kw_test(**kwargs):
    for kw in kwargs:
        print(kw, 'is', kwargs[kw])

kw_test(name='count', value=1)

This prints:

name is count
value is 1

An example of keyword arguments in action is the Python dictionary constructor:

d = dict(type='hat', style='stetson', color='brown', size='10')

This creates a dictionary like this:

{'style': 'stetson', 'color': 'brown', 'size': '10', 'type': 'hat'}

One thing to note about this is that the dictionary keys must be strings that form valid Python variable names. In general, of course, a dictionary key can be any immutable object.

Recipe for mixing parameters

There are four different ways of declaring parameters in Python functions:

It would be quite rare to use all of these, but is isn’t impossible. In general it is best to declare the arguments in the order shown, that is:

Most other combinations will cause syntax errors. Some other combinations are legal but generally not that useful.

Summary

Python provides several ways to add optional parameters to functions. This allows you to add extra functionality without complicating the default use of the function.