Home Lesson-4.2

Lesson-4.1

Functions

Introduction

In mathematics, a function is an object that accepts one or more inputs and produces one or more outputs. For example, , is a function that accepts a number and returns the square of that number. Functions in Python play a similar role, but are much more richer than their mathematical counterparts. Let us quickly convert the mathematical function, , into a Python function:

The code given above is called the definition of function f. def is the keyword used to define functions. f is the name of the function. x is a parameter of the function. Lines 2 and 3 make up the body of the function and are indented. The body of a function is a collection of statements that describe what the function does. At line-3, the value stored in variable y is returned. return is the keyword used for this purpose.

If we run the above code, we will not get any output. Functions are not executed unless they are called. The following code demonstrates what a function call looks like:

The output is:

square(2) is a function call. We use the name of the function, square, and pass the number 2 as an argument to it. The x in the function definition is called the parameter. The value that is passed to the function in the call is called the argument. This is a convention that we will follow throughout this lesson.

A visual representation of the terms we have defined so far is given below:

A mental model to understand functions:

 

Examples

We will look at a wide variety of function definitions. The focus will be on the syntactical aspects of function definitions.

When the code given above is executed, we get the following output:

Note that we didn't have to type print(foo()). We just had to call the function — foo() — since it already has the print statement inside it. But what happens if we type print(foo())? We get the following output:

If no explicit return statement is present in a function, None is the default value returned by it. When the interpreter comes across the print(foo()) statement, first the function foo() is evaluated. This results in the first line of the output. Since foo() has no explicit return statement, it returns None by default. That is why the second line in the output is None.

pass is a keyword in Python. When the interpreter comes across a pass statement, it doesn't perform any computation and moves on to the next line. The reason this is minimal is because it has only those features that are absolutely essential for a function definition to be syntactically valid: function name and at least one statement in the body.

Such functions might seem useless at first sight, but they do have their place in programming. While writing a complex piece of code, a coder may realize that she needs to define a function to perform a specific task. But she may not know the exact details of the implementation or it may not be an urgent requirement. In such a scenario, she will add a minimal function like the one given above in her code and name it appropriately. Implementing this function will become a task on her to-do list and will be taken up as and when the need arises.

foo() will always return 1. Line-3 is redundant. An example of a function having multiple returns that are not redundant:

The output is:

When evenOrOdd is called with an even number as argument, the return statement in line-3 is executed. When the same function is called with an odd number as argument, the return statement in line-5 is executed.

The exact mechanism of what happens here will become clear when we come to the lesson on tuples. In line-8, the first value returned by bound is stored in l and the second value returned by bound is stored in u.

When the above code is executed, it throws a NameError. Why does this happen? The Python interpreter executes the code from top to bottom. At line-2, f is a name that the interpreter has never seen before and therefore it throws a NameError. Recall that NameError occurs when we try to reference a name that the interpreter has not seen before.

The above code throws a SyntaxError.

Try calling bar() outside foo. What do you observe?

 

Docstrings

Consider the following function:

The string immediately below the function definition is called a docstring. From the Python docs:

A docstring is a string literal that occurs as the first statement in a module, function, class, or method definition. Such a docstring becomes the __doc__ special attribute of that object.

Ignore unfamiliar terms such as "module" and "class". For now, it is sufficient to focus on functions. Adding the docstring to functions is a good practice. It may not be needed for simple and obvious functions like the one defined above. As the complexity of the functions you write increases, docstrings can be a life safer for other programmers reading your code.

The docstring associated with a given function can be accessed using the __doc__ attribute:

This gives 'Return the square of x.' as output.