Function In Python
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.
def display_message():
- to define the function, we will use the keyword
def
followed by the name of the functiondisplay_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
""" 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
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
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 is a piece of information the function needs to do its job
- the variable
title
in the definition of functionfavorite_book
is an example of parameter
- an argument is a piece of information that is passed from a function call to a function
- The value
harry_potter
infavorite_book(title)
is an example of an argument
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
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
namedmake_shirt
that requires two parameters —size
andmessage
- 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 arguments —
xl
andI code in Python
- 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
A keyword argument is essentially name-value pair that we pass to a function, wherename
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")
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 frommake_shirt
function and will provide the default value for parametermessage
# 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:
...python
make_shirt("large", "I love Java.")
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.
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 variableWe 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
andalbum_2
that stored the function output value
We will first write the function as we have done in above example, and then get the argument values onceinput
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
andalb_name
to call the function - lastly, we print the
album_info
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 argumentIn 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
andshipped_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 fromordered_list
, store it in the variableordered_item
, print it and finally append it to the listshipped_items
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']
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
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 thesandwich
function that takes thesize
of the sandwich as parameter butitems
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.
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 variableprofile_dexter
- then we called the second function,
print_profile
by providing the variableprofile_dexter
as an argument
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 usingimport
statement.
Animport
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
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.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
Rather than importing all the functions inside a file, we can import a specific function from a module.
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
function_name()
As you can see, in this way, we don’t need to provide the name of module whenever we call a function
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 functionfrom module_name import *
function_name()
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
from module_name import function_name as fn
fn()
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.import module_name as mn
mn.function_name()
Last modified 4mo ago