Categories
Python

Part 7: PYTHON’S FUNCTION

In this article, we will learn how to define function in Python, to call a function. Difference between positional and keyword arguments in function definition. Using list inside a function and finally, how to store and retrieve the functions from the file.

1. DEFINING PYTHON’s FUNCTION

Let’s first write a very simple Python function and then use it as an example to define the elements of a function

# defining the function
def display_message():
	# docstring to define the purpose of function
    """ fucntion will print a welcome message with todays learning theme """
    print("Hello everyone, in this section, we will learn about Python's functions.")

# calling the function
display_message()
Hello everyone, in this section, we will learn about Python's functions.

a. Keyword Definition

def display_message():
  • to define the function, we will use the keyword def followed by the name of the function display_message
  • if the function do need some information to do its job, this piece of information is provided within the parenthesis ( )
  • the function ends with a colon : sign

b. Body of the function

""" function will print a welcome message with todays learning theme """
    print("Hello everyone, in this section, we will learn about Python's functions.")
  • all indented lines follow the colon sign : represents the body of the function
  • text within the triple commas is called docstring and it give us the opportunity to tell the reader of code, what the function does. It is essentially the comments, Python uses it to generate documentation for the functions in your programs
  • the print() statement runs any time we call the function

c. Calling a function

display_message()
  • to execute the function, we just need to write the name of function (and provide any information, within parenthesis, if function needs it) This call essentially tells Python to execute the code in the function

1.1. Passing Information (arguments) to a Function

Let’s move a step further and write a function that accepts some information to work inside the function. This is called argument

# defining function with argument, title
def favorite_book(title):
	# docstring
    """ printing the favorite book """
    print(f"One of my favorite book is {title.title()}.")

favorite_book('harry potter')
One of my favorite book is Harry Potter.

a. Parameter

  • a parameter is a piece of information the function needs to do its job
  • the variable title in the definition of function favorite_book is an example of parameter

b. Argument

  • an argument is a piece of information that is passed from a function call to a function
  • The value harry_potter in favorite_book(title) is an example of an argument

2. PASSING ARGUMENTS

In the above example, the function definition only include one parameter and therefore one argument is supplied in the function call. However, function can have multiple parameters and arguments. You can pass arguments to your functions in a number of ways:

  • ** positional arguments** — which need to be in the same order as the parameters;
  • keyword arguments — where each argument has a variable name and a value, that is, name-value pair;
  • and lists and dictionaries of values

2.1. Positional Arguments

When we call a function, Python match each argument in the function call with each parameter in the function definition. Therefore the values matched up this way (based on the order of the arguments ) are called positional arguments. Let’s write a function with positional arguments:

# defining function with two parameters, named, size and message
def make_shirt(size, message):
    # docstring
    """To print the size and message on the shirt """
    # print statement
    print(f"You have ordered the shirt in size {size.upper()}\nThe following message will be printed on the shirt: {message}")

# call the function
# positional arguments
make_shirt("xl", "I code in Python")
You have ordered the shirt in size XL
The following message will be printed on the shirt: I code in Python
  • we defined the function named make_shirt that requires two parameterssize and message
  • we then write the body of function with a print statement using the given values of parameters
  • lastly, we call a function by providing the argumentsxl and I code in Python

Important Points

  • Multiple function call: You can call the function as many times as you want with new set of arguments. This makes the function very powerful — write code once and use it several times
  • Order matters in positional arguments: Make sure to provide the arguments in same order as the parameters in function definition

2.2. Keyword Arguments

A keyword argument is essentially name-value pair that we pass to a function, where name is the parameter name . Therefore, as we explicitly provides the name of parameter in the argument, the order of arguments doesn’t matter. We will rewrite the above example using keyword arguments:

# defining function with two parameters, named, size and message
def make_shirt(size, message):
    # docstring
    """To print the size and message on the shirt """
    # print statement
    print(f"You have ordered the shirt in size {size.upper()}\nThe following message will be printed on the shirt: {message}")

# call the function
# keyword arguments
make_shirt(message = "I code in Python.", size ="xl")
You have ordered the shirt in size XL
The following message will be printed on the shirt: I code in Python.

As you can see that when we call the function, we used the name-value pair, where name is the name of parameter in the function definition. In this case, the order of arguments doesn’t matter.

make_shirt(message = "I code in Python.", size ="xl")

2.3. Default Values

When writing a function, we can define ** default value** for each parameter. In this case, if an argument for a parameter is provided in the function call, Python uses the argument value, otherwise, it uses the parameter’s default value (as provided in function definition) In the following example, we will copy the code from make_shirt function and will provide the default value for parameter message

# defining function with two parameters, named, size and message
# default value of paramter, message, is provided
def make_shirt(size, message = 'I love Python.'):
    # docstring
    """To print the size and message on the shirt """
     # print statement
    print(f"You have ordered the shirt in size {size.upper()}\nThe following message will be printed on the shirt: {message}")

# call the function
# using default value of parameter
make_shirt("large")
You have ordered the shirt in size LARGE
The following message will be printed on the shirt: I love Python.

Note that the parameter with default value must be the last parameter(s) In this example, we will overwrite the default value of the parameter:

...
make_shirt("large", "I love Java.")

3. RETURN VALUES

A function doesn’t always have to display its output directly (like printing some message, as we have done so far). Instead, we can write a function that process some data and then return a value or set of values. The value the function returns is called a return value. This** return value** can be used anyway we want. NOTE: When you call a function that returns a value, you need to provide a variable where the return value can be stored.

3.1. Returning A Simple Value

Let’s write a simple function that returns the string:

# defining function with two parameters, named, city and country
def city_country(city, country):
     # docstring
    """ combining the parameters and returning formatted_string"""
    # storing values of given parameter inside a variable
    formatted_string = f"{city.title()} , {country.title()}"
    # returning the variable value
    return formatted_string

# calling the function
# storing the returned value inside country_1
country_1 = city_country("london", "england")
print(country_1)
London , England

when we call the function city_country we stored its returned value in separate variable called country_1 and then print that variable

3.2. Making an Argument Optional

We can use empty default values for a parameter to make an argument optional. As a rule, all (empty) default value parameter(s) are moved to the end of the parameters list

Let’s write a function which stores a dictionary containing artist name and album title. However, we also would like to store an optional parameter — i.e, no of tracks in the album. Here is how we deal with this situation:

# defining function with three parameters
# last parameter, tracks, is optional with empty default value
def make_album(artist_name, album_title, tracks = ''):
     # docstring
    """ making album """
	# making dictionary from the parameter values
    album_dic = {'artist_name': artist_name, 'album_title': album_title}
    # checking if the number of tracks are provided in argument
    if tracks:
        # if yes, add it to the dictionary
        tracks_integer = int(tracks)
        album_dic['tracks'] = tracks_integer
    # returning the album_dict dictionary
    return album_dic

# calling function 1 without 'tracks'
album_1 = make_album('usher', 'confessions')

# calling function 2 with 'tracks'
album_2 = make_album ('akon', 'konvicted', tracks ='13')

# printing albums made from returned values of the function
print(album_1)
print(album_2)
{'artist_name': 'usher', 'album_title': 'confessions'}
{'artist_name': 'akon', 'album_title': 'konvicted', 'tracks': 13}
  • we have used the parameter tracks in the function definition as an optional argument
  • in the body of function, we made a dictionary with required parameter values, then,
  • we used if statement to check whether the user provided optional argument, tracks. If yes, we concatenated that value to the dictionary
  • we used return statement to output the dictionary
  • we call the function two times — one with tracks and one without it
  • we then print the variables album_1 and album_2 that stored the function output value

3.3. Using a Function with a while Loop

We will first write the function as we have done in above example, and then get the argument values once input statements

# defining function with two required parameters
def make_album(artist_name, album_title):
     # docstring
    """ storing parameter values in dictionary and returning it"""
    # making dictionary from the parameter values
    album_dic = {'artist_name': artist_name, 'album_title': album_title}
    # returning the album_dict dictionary
    return album_dic

# while loop will run as long as it gets two input values
while True:
    a_name = input("Enter the artist name: ")
    alb_name = input("Enter the album name: ")
    break

# calling function 
album_info = make_album(a_name, alb_name)
# printing album made from returned value of the function
print(album_info)
Enter the artist name: usher
Enter the album name: confessions
{'artist_name': 'usher', 'album_title': 'confessions'}
  • the above example only takes a pair of response
  • both user inputs were mandatory and loop breaks after that
  • we used the input values, stored inside the variables, a_name and alb_name to call the function
  • lastly, we print the album_info

4. PASSING A LIST IN FUNCTION

Python’s functions are very flexible to be used with different data types. In the following example, we will use as a list parameter of a function:

# defining function with list as a parameter
def show_magicians(magicians):
     # docstring
    """ a function to print to content of the list """
    # printing items of list, using for loop
    print("These are some great magicinans in Sweden:")
    for magician in magicians:
        print(magician.title())

# calling function by providing list as argument
magicians = ['abbott', 'costello', 'shawn', 'michael']
show_magicians(magicians)
These are some great magicinans in Sweden:
Abbott
Costello
Shawn
Michael

In the above example, we passed a single list. However, we are free to supply a series of list as argument

4.1. Modifying a List in a Function

In following example, we are going to use two lists in one function with purpose of moving the list items from one list to another (i.e, modifying the list)

# defining function with two parameters
# both of them are Python list
def inventory(ordered_items, shipped_items):
    # docstring
    """ shifting items from one list(ordered) to another(shipped) """
    # while loop will run as long as ordered_item list is not empty
    while ordered_items:
        ordered_item = ordered_items.pop()
        print(f"Shipping: {ordered_item.title()}")
        shipped_items.append(ordered_item)

# defining the arguments (lists) and calling the function
ordered_items = ['apple', 'orange', 'strawberry']
shipped_items = []
inventory(ordered_items, shipped_items)
Shipping: Strawberry
Shipping: Orange
Shipping: Apple
  • we used two lists, ordered_items and shipped_items as parameters in the definition of the function
  • we used while loop which keep running until the list, ordered_list is empty
  • we pop each item from ordered_list , store it in the variable ordered_item , print it and finally append it to the list shipped_items

4.2. Working with the Copy of a List

Let suppose, we want to keep the list ordered_items unmodified. Here is the trick in python on how to stop the list to be modified — when call the function, use the following syntax:

function_name(list_name[:])

The slice notation [:] makes a copy of the list.

...
# defining the arguments (lists) and calling the function
# we will use [:] to work with copy of list
ordered_items = ['apple', 'orange', 'strawberry']
shipped_items = []
inventory(ordered_items[:], shipped_items)

print("\nHere is a check that old list is still unmodified:")
print(ordered_items)
Shipping: Strawberry
Shipping: Orange
Shipping: Apple

Here is a check that old list is still unmodified:
['apple', 'orange', 'strawberry']

5. PASSING AN ARBITRARY NUMBER OF ARGUMENTS

Sometimes function need to process the unknown number of parameters. To pass these arbitrary number of arguments, we need to add an asterisk * before a parameter name in the function definition. This asterisk * in the parameter name, tells Python to make an empty tuple and load whatever values it receives into this tuple. NOTE: Python loads the arguments into a tuple, even if the function receives only one value

# defining function that takes arbitrary no of parameters
def sandwich(*items):
    # docstring
    """Print the sandwich content, selected by the user """
    print("Your sandwich includes the following items:")
    for item in items:
        print("- " + item)

# calling function with two arguments
sandwich('egg', 'cheese')
# calling function with four arguments
sandwich('egg','beef','mushroom','cheese')
Your sandwich includes the following items:
- egg
- cheese
Your sandwich includes the following items:
- egg
- beef
- mushroom
- cheese
  • we wrote the function to print all the items in a sandwich
  • as we don’t know in advance that how many arguments does user supply, so we added an asterisk before a parameter name. In this way, our function can handle arbitrary number of arguments

5.1. Mixing Positional and Arbitrary Arguments

If we want a function to accept different kinds of arguments, the parameter that accepts an arbitrary number of arguments must be placed last in the function definition.

Python first matches the positional and keyword arguments and then process any remaining arguments in the final parameter. Let’s modify the sandwich function that takes the size of the sandwich as parameter but items parameter will be arbitrary:

# defining function that takes one required and 
# one arbitrary parameter
def sandwich(size, *items):
     # docstring
    """Print the sandwich content, selected by the user """
    print("You have ordered a " + size + " sandwich.")
    # this section runs only if 'items' are provided
    if items:
        print("Your sandwich includes the following items:")
        for item in items:
            print("- " + item)
        
# calling function example 1
sandwich('12 inches','beef','mushroom','cheese')
# calling function example 2
sandwich('6 inches')
You have ordered a 12 inches sandwich.
Your sandwich includes the following items:
- beef
- mushroom
- cheese
You have ordered a 6 inches sandwich.

5.2. Using Arbitrary Keyword Arguments

Until now, functions with arbitrary number of arguments, all of them are of one type (for example, sandwich items in the above example). However, if they are not of same type, we can use the name-value pair in the argument.

The double asterisks ** before the parameter tells Python to create an empty dictionary and load whatever name-value pairs it receives (in arguments) into this dictionary

# defining function to build user profile
def build_profile(first,last,**user_info):
    # docstring
    """ build user profile and store its inside dict""" 
    user = {}
    user['first_name'] = first
    user['last_name'] = last
    for key,value in user_info.items():
        user[key] = value
    return user

# defining function to print the dictionary
def print_profile(profile_info):
    for key, value in profile_info.items():
        print(f"{key}: {value}")

# calling build_profile function
profile_dexter = build_profile('dexter', 'morgan',
age = 22,
location ='florida',
profession ='forensic analyst')

# calling print_profile function
# dictionary we just made by calling build_profile function
# is used as argument
print_profile(profile_dexter)
first_name: dexter
last_name: morgan
age: 22
location: florida
profession: forensic analyst
  • we wrote two functions, first, build_profile to build the profile (in form of dictionary) using arbitrary number of (keyword) arguments and another, print_profile to print the key-value pair of the dictionary returned from the first function
  • we first call the build_profile function and store its value (dictionary) inside a variable profile_dexter
  • then we called the second function, print_profile by providing the variable profile_dexter as an argument

6. STORING YOUR FUNCTIONS IN MODULES

We can go a step further by storing our functions in a separate file called a module and then importing that module into our main program using import statement.

An import statement tells Python to make the code in a module(file) available in the currently running program file.

A module is a file ending in .py that contains the code we want to import into our program

6.1. Importing an Entire Module

a. General syntax to import:

import module_name

The above line import module_name tells Python to open the file module_name.py and copy all the functions from it into this program.

b. General syntax to call the function:

module_name.function_name()

Enter the name of the module we imported, module_name, followed by the name of the function, function_name(), separated by a dot . EXAMPLE: Let suppose we store the function to build the profile in a separate file called build_profile_module.py then import the module and call this function:

# importing moduele
import build_profile_module

# calling 'build_profile' function
person_1 = build_profile_module.build_profile('dexter', 'morgan',
age = 22,
location ='florida',
profession ='forensic analyst')

# calling 'print_profile' function
print_profile(person_1)
first_name: dexter
last_name: morgan
age: 22
location: florida
profession: forensic analyst

6.2. Importing Specific Functions

Rather than importing all the functions inside a file, we can import a specific function from a module.

a. General syntax to import

Importing a single function:

from module_name import function_name

Importing series of function: We can import as many functions as we want from a module by separating each function’s name with a comma

from module_name import function_0, function_1, function_2

b. General syntax to call the function:

function_name()

As you can see, in this way, we don’t need to provide the name of module whenever we call a function

6.3. Importing All Functions in a Module

We can tell Python to import every function in a module by using the asterisk * operator. But you might be questioning that we can import all the function using the method described in 6.1, then we need this method? Using this (asterisk) way, we don’t need to use the module name anymore when calling the function

a. General syntax to import:

from module_name import *

b. General syntax to call the function:

function_name()

6.4. Give Function an Alias

A couple of reasons to use alias for a function name:

  • name of a function we are importing might conflict with an existing name in our program
  • function name is long, so we can use a short one

a. General syntax to import:

from module_name import function_name as fn

b. General syntax to call the function:

fn()

6.5. Give Module an Alias

In section 6.1, we used import module_name and then we need to use the module name every time we call the function (Remember the syntax?) Therefore to avoid using the long module name, we can import module using alias.

a. General syntax to import:

import module_name as mn

b. General syntax to call the function:

mn.function_name()

Leave a Reply