Defining functions

This chapter will discuss how to define your own functions, pass arguments to them and get back results. You'll also learn more about the print() built-in function.

def

Use the def keyword to define a function. The function name is specified after the keyword, followed by arguments inside parentheses and finally a : character to end the definition. It is a common mistake for beginners to miss the : character. Arguments are optional, as shown in the below program.

# no_args.py
def greeting():
    print('-----------------------------')
    print('         Hello World         ')
    print('-----------------------------')

greeting()

The above code defines a function named greeting and contains three statements as part of the function. Unlike many other programming languages, whitespaces are significant in Python. Instead of a pair of curly braces, indentation is used to distinguish the body of the function and statements outside of that function. Typically, 4 spaces is used, as shown above. The function call greeting() has the same indentation level as the function definition, so it is not part of the function. For readability, an empty line is used to separate the function definition and subsequent statements.

$ python3.9 no_args.py
-----------------------------
         Hello World         
-----------------------------

info Functions have to be declared before they can be called. As an exercise, call the function before declaration and see what happens for the above program.

info As per PEP 8: Style Guide for Python Code, it is recommended to use two blank lines around top level functions. However, I prefer to use a single blank line. For large projects, specialized tools like pylint and black are used to analyze and enforce coding styles/guidelines.

info To create a placeholder function, you can use the pass statement to indicate no operation. See docs.python: pass statement for details.

Accepting arguments

Functions can accept one or more arguments, specified as comma separated variable names.

# with_args.py
def greeting(ip):
    op_length = 10 + len(ip)
    styled_line = '-' * op_length
    print(styled_line)
    print(f'{ip:^{op_length}}')
    print(styled_line)

greeting('hi')
weather = 'Today would be a nice, sunny day'
greeting(weather)

In this script, the function from the previous example has been modified to accept an input string as the sole argument. The len() built-in function is used here to get the length of a string value. The code also showcases the usefulness of variables, string operators and string formatting.

$ python3.9 with_args.py
------------
     hi     
------------
------------------------------------------
     Today would be a nice, sunny day     
------------------------------------------

As an exercise, modify the above program as suggested below and observe the results you get.

  • add print statements for ip, op_length and styled_line variables at the end of the program (after the function calls)
  • pass a numeric value to the greeting() function
  • don't pass any argument while calling the greeting() function

info The argument variables, and those that are defined within the body, are local to the function and would result in an exception if used outside the function. See also docs.python: Scopes and Namespaces and docs.python: global statement.

info Python being a dynamically typed language, it is up to you to sanitize input for correctness. See also docs.python: Support for type hints and realpython: Python Type Checking Guide.

Default valued arguments

A default value can be specified during the function definition. Such arguments can be skipped during the function call, in which case they'll use the default value. They are also known as keyword arguments. Here's an example:

# default_args.py
def greeting(ip, style='-', spacing=10):
    op_length = spacing + len(ip)
    styled_line = style * op_length
    print(styled_line)
    print(f'{ip:^{op_length}}')
    print(styled_line)

greeting('hi')
greeting('bye', spacing=5)
greeting('hello', style='=')
greeting('good day', ':', 2)

There are various ways in which you can call functions with default values. If you specify the argument name, they can be passed in any order. But, if you pass values positionally, the order has to be same as the declaration.

$ python3.9 default_args.py
------------
     hi     
------------
--------
  bye   
--------
===============
     hello     
===============
::::::::::
 good day 
::::::::::

As an exercise, modify the above script for the below requirements.

  • make the spacing work for multicharacter style argument
  • accept another argument with a default value of single space character that determines the character to be used around the centered ip value

As another exercise, what do you think will happen if you use greeting(spacing=5, ip='Oh!') to call the function shown above?

info Arguments declared without default values can still be used as keyword arguments during function call. This is the default behavior. Python provides special constructs / and * for stricter separation of positional and keyword arguments. See docs.python: Special parameters for details.

Return value

The default return value of a function is None, which is typically used to indicate the absence of a meaningful value. The print() function, for example, has a None return value. Functions like int(), len() and type() have specific return values, as seen in prior examples.

>>> print('hi')
hi
>>> value = print('hi')
hi

>>> value
>>> print(value)
None
>>> type(value)
<class 'NoneType'>

Use the return statement to explicitly give back a value when the function is called. You can use this keyword by itself as well (default value is None).

>>> def num_square(n):
...     return n * n
... 
>>> num_square(5)
25
>>> num_square(3.14)
9.8596

>>> op = num_square(-42)
>>> type(op)
<class 'int'>

info On encountering a return statement, the function will be terminated and further statements, if any, present as part of the function body will not be executed.

info A common beginner confusion is mixing up the print() function and the return statement. See stackoverflow: What is the formal difference between “print” and “return”? for examples and explanations.

A closer look at the print() function

The help documentation for the print() function is shown below.

help print

As you can see, there are four default valued arguments. But, what does value, ..., mean? It indicates that the print() function can accept arbitrary number of arguments. Here's some examples:

# newline character is appended even if no arguments are passed
>>> print()

>>> print('hi')
hi
>>> print('hi', 5)
hi 5

>>> word1 = 'loaf'
>>> word2 = 'egg'
>>> print(word1, word2, 'apple roast nut')
loaf egg apple roast nut

If you observe closely, you'll notice that a space character is inserted between the arguments. That separator can be changed by using the sep argument.

>>> print('hi', 5, sep='')
hi5
>>> print('hi', 5, sep=':')
hi:5
>>> print('best', 'years', sep='.\n')
best.
years

Similarly, you can change the string that gets appended to something else.

>>> print('hi', end='----\n')
hi----
>>> print('hi', 'bye', sep='-', end='\n======\n')
hi-bye
======

info The file argument will be discussed later. Writing your own function to accept arbitrary number of arguments will also be discussed later.

Docstrings

Triple quoted strings are also used for multiline comments and to document various part of a Python script. The latter is achieved by adding help content as string literals (but without being assigned to a variable) at the start of a function, class, etc. Such literals are known as documentation strings, or docstrings for short. Idiomatically, triple quoted strings are used for docstrings. The help() function reads these docstrings to display the documentation. There are also numerous third-party tools that make use of docstrings.

Here's an example:

>>> def num_square(n):
...     """
...     Returns the square of a number.
...     """
...     return n * n
... 
>>> help(num_square)

Calling help(num_square) will give you the documentation as shown below.

num_square(n)
    Returns the square of a number.

info See docs.python: Documentation Strings for usage guidelines and other details.