Functions

Learning Objectives

By the end of this chapter, you will be able to:

  • Describe the various function types in Python
  • Define global and local variables
  • Define a function that takes in a variable number of arguments

This lesson introduces functions in Python. We look at the various types of functions and define our own.

Introduction

In the previous chapter, we covered the following topics:

  • How to use looping structures
  • How to branch within looping structures
  • How to break out of loops

We will continue to build on this knowledge by implementing what we have learned, to build functions in Python.

Functions are an integral part of the Python programming language, and a lot of languages, really. Throughout this book, you have already encountered some built-in functions, especially when dealing with certain data structures.

Functions are an easy way to group a few lines of code that implement a functionality together. This is especially useful if the code in question will be used several times in different parts of your program. You may want to use functions to abstract away some complex code that you need in your programs. You can think of functions as mini-programs within your bigger program that implement specific tasks.

It is important to remember that while it is tempting to tuck a lot of functionality into a single function, it is better to write functions that only perform one specific task. This makes it easier to modularize your code, and, in the long run, it is more maintainable and easier to debug.

Functions may take optional inputs to work with and may optionally return a value or values.

The three main types of functions in Python are as follows:

  • Built-in functions
  • User-defined functions
  • Anonymous functions

Built-In Functions

The Python interpreter has a number of built-in functions and types that are always available. These are called built-in functions, and they can be used anywhere in your code, without the need of any importation.

Some of the built-in functions that we have already encountered in this book are as follows:

  • input([prompt]): This optionally prints the prompt to the terminal. It then reads a line from the input and returns that line.
  • print(): Prints objects to the text stream file or the terminal.
  • map(): Returns an iterator that applies a function to every item of the iterable, yielding the results.

For example, we recently used the built-in print() function to output results; the following is another simple demonstration:

print("Hello world")

This results in the following:

Hello world

User-Defined Functions

As the name suggests, these are functions that are written by the user, to aid them in achieving a specific goal. The main use of functions is to help us organize our programs into logical fragments that work together to solve a specific part of our problem.

The syntax of a Python function looks like this:

def function_name( parameter_one, parameter_two, parameter_n ):

# Logic goes here

return

To define a function, we can use the following steps:

  1. Use the def keyword, followed by the function name.
  2. Add parameters (if any) to the function within the parentheses. End the function definition with a full colon.
  3. Write the logic of the function.
  4. Finally, use the return keyword to return the output of the function. This is optional, and if it is not included, the function automatically returns None.

A user-defined function must have a name. You can give it any name that you like, and it is a good practice to make the name as descriptive of the task that the function achieves as possible. For example, if you are writing a function that calculates the monthly average rainfall from a list of values, it is better to name the function calculate_monthly_average_rainfall() than calculate(). Remember, code is written to be read by humans, not computers. Make it easy for other humans to immediately understand what a function does, just by looking at the name:

def calculate_monthly_average_rainfall(list_of_annual_values):

# Loop over list and calculate average here

return average

Parameters are the information that needs to be passed to the function, in order for it to do its work. Parameters are optional, and they are separated by commas and placed between parentheses after the function name. A function can have any number of parameters, and there is really no limit to this.

Calling a Function

Calling a function means executing the logic that is defined inside of the function. This can be done from the Python interactive prompt, or from within some other part of your code. Functions are often called from other functions.

If we were to call the function that we defined earlier (the one that calculates the monthly rainfall average), we would just do something like this:

annual_values = []

calculate_monthly_average_rainfall(annual_values)

Note that the names of the arguments that we pass when we are calling the function in this instance do not have to match the parameter names that the function expects. What is important is that no matter what you pass to the function when calling it, the function will refer to this parameter as list_of_annual_values internally.

This transitions us smoothly to our next sub-topic: global and local variables.

Global and Local Variables

Variables that are defined inside of a function body are called local variables, as they are only accessible inside the function. They are said to have a local scope.

Variables that are defined outside of a function body are called global variables, as they are accessible both outside and inside of the functions. They are said to have a global scope because of this.

Exercise 19: Defining Global and Local Variables

In this exercise, we will define global and local variables. We will also demonstrate the difference between global and local variables:

  1. First, define a global variable, number, and initialize it to 5:

    number = 5

  2. Then, define a function called summation that takes two named parameters- first and second:

    def summation(first, second):

  3. Inside of the function, add up the two parameters that were passed in and the global variable number:

    total = first + second + number

  4. Return the final total:

    return total

  5. Call the summation function with two parameters, as expected (10 and 20):

    summation(10, 20)

  6. Print out the initial value of the number:

    print("The first number we initialised was " + str(number))

  7. Try to access the local variable total:

    print("The total after summation is " + str(total))

    Note the use of the built-in function, str(), which returns the string version of an object.

    The final code is as follows:

    # Initialise global variable "number" to 5

    number = 5

    """

    Define function "summation" that takes two parameters

    Note that the function accesses the global variable "number"

    """

    def summation(first, second):

    # Add the parameters and global number together

    total = first + second + number

    # Return result

    return total

    # Call the "summation" function with two parameters as expected

    summation(10, 20)

    # Print out the initial value of "number"

    print("The first number we initialised was " + str(number))

    # Try to access the local variable "total"

    print("The total after summation is " + str(total))

  8. Run this script. The output of running this code is as follows:

    Python 3.6.1 (default, Dec 2015, 13:05:11)

    [GCC 4.8.2] on linux

    The first number we initialised was 5

    Traceback (most recent call last):

    File "main.py", line 21, in <module>

    print("The total after summation is " + str(total))

    NameError: name 'total' is not defined

    As you can see, this results in an error, because we are trying to access the local variable total from the global scope. This is just to demonstrate that we cannot access local variables globally.

  9. Now, change the code to the following; we will get different output upon calling the function:

    # Initialise global variable "number" to 5

    number = 5

    """

    Define function "summation" that takes two parameters

    Note that the function accesses the global variable "number"

    """

    def summation(first, second):

    # Add the parameters and global number together

    total = first + second + number

    # Return result

    return total

    # Call the "summation" function with two parameters as excepted

    # Assign the result of "summation" to the variable "outer_total"

    outer_total = summation(10, 20)

    # Print out the initial value of "number"

    print("The first number we initialised was " + str(number))

    # Try to access the local variable "total"

    print("The total after summation is " + str(outer_total))

    Notice that we are now assigning the result of the summation function to the outer_total variable.

  10. Run the script again. The output now changes to what we expect, without errors, and it looks as follows:

    Python 3.6.1 (default, Dec 2015, 13:05:11)

    [GCC 4.8.2] on linux

    The first number we initialised was 5

    The total after summation is 35

Function Return

The return statement in Python is used within functions, to actually return something to the caller of the function. Without a return statement, every function will return None.

Consider the following function:

def summation(first, second):

total = first + second

print("The total is " + str(total))

summation(10, 20)

The output of this code is:

Python 3.6.1 (default, Dec 2015, 13:05:11)

[GCC 4.8.2] on linux

The total is 30

Note that the summation function, in this case, does not have a return statement. As mentioned previously, a return statement is not necessary for all functions. The purpose of this function in particular is to print out the total, and in this case, it is not necessary to return anything, as the printing can be done within the function.

However, a return statement is required if you need to use the result of calling a function for any further processing in your code. Consider the following variation:

def summation(first, second):

total = first + second

return total

outer_total = summation(10, 20) * 2

print("Double the total is " + str(outer_total))

In this variation, we can see that the summation function returns the sum of the passed-in values. This returned value is then multiplied by two and assigned to the outer_total variable. This way, the function has, in essence, abstracted away the operation of summing the two numbers.

Of course, this is just a rudimentary example, and with this knowledge, you can begin to build more complex functions and programs.

Using main()

Most other programming languages (for example, Java and C++) require a special function, called main(), which tells the operating system what code to execute when a program is invoked. This is not necessary in Python, but you will find that it is a good and logical way to structure a program.

Before the Python interpreter executes our program, it defines a few special variables. One of them is __name__, and it will automatically be set to __main__ if our program will be executed by itself, in a standalone fashion.

However, if our program will be imported by another program, then __name__ will be set to the name of that other program. We can easily determine whether the program is standalone or is being used by another program as an import. Based on that, we can decide to either execute or exclude some of the code in a program.

The following is an example that uses the main() function:

def summation(first, second):

total = first + second

return total

def main():

outer_total = summation(10, 20) * 2

print("Double the total is " + str(outer_total))

if __name__ == "__main__":

main()

Without the if __name_ == __main__ check and declaration, our script would still be executable. All we would have to do is declare or call our summation() function.

In Python, there is nothing special about the name main. We could have called this function anything that we wanted. We chose main to be consistent with some of the other languages.

Function Arguments

As mentioned earlier, parameters are the information that need to be passed to the function for it to do its work. Although parameters are also commonly referred to as arguments, arguments are thought of more as the actual values or references assigned to the parameter variables when a function is called at runtime. In simpler terms, arguments are to functions as ingredients are to a recipe.

Python supports several types of arguments; namely:

  • Required arguments
  • Keyword arguments
  • Default arguments
  • A variable number of arguments

Required Arguments

Required arguments are the types of arguments that have to be present when calling a function. These types of arguments also need to be in the correct order for the function to work as expected.

Consider the following code snippet:

def division(first, second):

return first/second

You have to pass the arguments first and second for the function to work. You also have to pass the arguments in the correct order, as switching them will yield completely different results.

You would then call the function like this:

quotient = division(10, 2)

The result, as expected, would be as follows:

Python 3.6.1 (default, Dec 2015, 13:05:11)

[GCC 4.8.2] on linux

5.0

Keyword Arguments

If it is necessary that you call all of the parameters in the right order, you can use keyword arguments in your function call. You can use these to identify the arguments by their parameter names. Let's consider the previous example to make this a bit clearer:

def division(first, second):

return first/second

quotient = division(second=2, first=10)

print(quotient)

As you can see, we have intentionally passed arguments in the wrong order by swapping their positions. The difference here is that we used the names of the arguments when passing them. By doing this, we corrected our mistake, and the function will receive its parameters in the right order and give us the correct (and expected) output, which is as follows:

Python 3.6.1 (default, Dec 2015, 13:05:11)

[GCC 4.8.2] on linux

5.0

Keyword arguments are very powerful, and they ensure that no matter which order we pass arguments in, the function will always know which argument goes where.

Default Arguments

Default arguments are those that take a default value if no argument value is passed during the function call. You can assign this default value with the assignment operator, =, just like in the following example:

def division(first, second=2):

return first/second

quotient = division(10)

print(quotient)

The output for this example is the same as that of the previous examples.

Note that even if the argument named second has a default value, you can still pass a value to it, and this passed value will override the default value. This means that the function will promptly ignore the default value and use whatever value you passed to it.

The following is an example with the default argument where a value is passed:

def division(first, second=2):

return first/second

quotient = division(10, 5)

print(quotient)

As expected, the output of this snippet is:

Python 3.6.1 (default, Dec 2015, 13:05:11)

[GCC 4.8.2] on linux

2.0

Variable Number of Arguments

It might so happen that you want to allow a function to receive any number of variables, and then process them. Wouldn't it be convenient if you could pass a variable number of arguments to this function? Well, you're in luck! This is possible in Python by using the special * (asterisk) syntax.

The following is an example of using *args:

def addition(*args):

total = 0

for i in args:

total += i

return total

answer = addition(20, 10, 5, 1)

print(answer)

Note that you don't have to name the variable *args. You could have named it *numbers, and the function would have worked just as well.

Activity 19: Function Arguments

Write a function that receives n number of arguments; using a continue statement, skip integers and print out all other values.

The steps are as follows:

  1. Define a function named print_arguments, with a variable number of arguments.
  2. Use a for loop to iterate over the arguments.
  3. Use a check to see whether the value passed is of the integer type. If it is, use the continue statement to ignore it.
  4. Print the arguments.

The output should be as follows:

>>> print_arguments(2, 3.4, "s", 1.0)

3.4

s

1.0

Note

Solution for this activity can be found at page 285.

Anonymous Functions

Anonymous functions in Python are also called lambda functions. This is because they use the keyword lambda in their definition.

Anonymous functions are so called because, unlike all of the other functions that we have looked at up to this point, they do not require to be named in their definition. The functions are usually throwaway, meaning that they are only required where they are defined, and are not to be called in other parts of the codebase.

The syntax of an anonymous function is as follows:

lambda argument_list: expression

The argument list consists of a comma-separated list of arguments, and the expression is an arithmetic expression that uses these arguments. You can assign the function to a variable to give it a name.

Exercise 20: Creating a Lambda Function

Let's look at a practical application of a lambda function. Suppose that you want to simply sum up two numbers in a function. There is no need to define a whole user-defined function for this if you are only going to use it once:

  1. Create a lambda function that takes two parameters - first and second:

    answer = lambda first, second : first + second

    print(answer(6, 9))

    Here, we have defined a lambda function that takes two parameters (first and second) and adds them up. We have then assigned the function to the answer variable, so that we have a way to refer to it.

  2. Now, call the function and print out the output, which looks like this:

    Python 3.6.1 (default, Dec 2015, 13:05:11)

    [GCC 4.8.2] on linux

    15

The true power of anonymous functions can be seen when they are used in combination with the map(), reduce(), or filter() functions.

The syntax of a map() function is as follows:

map(func, iterable)

The first argument, func, is the name of a function, and the second, iterable, is a sequence (for example, a list). map() applies the func function to all of the elements of the iterable sequence. It returns a new list, with the elements changed by func.

Let's suppose that you have the following list, and want to generate a new list with the squares of every item in the list:

numbers = [2, 4, 6, 8, 10]

One way to implement this would be:

numbers = [2, 4, 6, 8, 10]

squared = []

for num in numbers:

squared.append(num**2)

The for loop, in this case, can be replaced with a lambda function that serves the same purpose, like this:

lambda num: num ** 2

We can then use the map() function to apply this lambda function to each of the items in the list, in order to get their squares, like this:

squared = map(lambda num: num ** 2, numbers)

This will yield a map object, and, to cast this to a list, we use the list() function, like this:

squared = list(map(lambda num: num ** 2, numbers))

Our whole program then reduces to just three lines:

numbers = [2, 4, 6, 8, 10]

squared = list(map(lambda num: num ** 2, numbers))

print(squared)

The output of these lines is as follows:

Python 3.6.1 (default, Dec 2015, 13:05:11)

[GCC 4.8.2] on linux

[4, 16, 36, 64, 100]

This definitely shows the versatility of lambda/anonymous functions, and their ability to make our code more concise.

Activity 20: Using Lambda Functions

Write a lambda function that takes in two numerical values and returns the first value, raised to the power of the second value:

  1. Create a lambda function that takes in number and power and returns the value of the number raised to power.
  2. Assign it to a variable called answer.
  3. Print the answer variable.

The output should be as follows:

>>> print(answer(2, 4))

16

Note

Solution for this activity can be found at page 285.

Summary

In this chapter, we learned about the various types of functions in Python, as well as their differences, syntax, and use cases. We covered how and where to apply the different types of functions, and how they can be used to help break your programs into smaller sub-programs that achieve a specific purpose. We also saw how the use of functions can help use reuse functionality in our code and avoid repeating the same blocks of code.

With this knowledge, you should be able to build all sorts of well-structured programs that will be easy to read and understand, and which will make optimal use of repetitive functionality.

In the next chapter, we will take a look at lists and tuples; it will be our first chapter regarding the various data structures that Python offers.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.129.194.123