Functions

Most of the times, In a algorithm the statements keep repeating and it will be a tedious job to execute the same statements again and again and will consume a lot of memory and is not efficient. Enter Functions.

This is the basic syntax of a function

def funcname(arg1, arg2,... argN):

''' Document String'''

statements


return <value>

Read the above syntax as, A function by name "funcname" is defined, which accepts arguements "arg1,arg2,....argN". The function is documented and it is '''Document String'''. The function after executing the statements returns a "value".

In [1]:
print ("Hey CODECHEF!")
print ("How do you do?")
Hey CODECHEF!
How do you do?

Instead of writing the above two statements every single time it can be replaced by defining a function which would do the job in just one line.

Defining a function firstfunc().

In [2]:
def firstfunc():
    print ("Hey CODECHEF!")
    print ("How do you do?")  
In [3]:
firstfunc()
Hey CODECHEF!
How do you do?

firstfunc() every time just prints the message to a single person. We can make our function firstfunc() to accept arguements which will store the name and then prints respective to that accepted name. To do so, add a argument within the function as shown.

In [4]:
def firstfunc(username):
    print ("Hey", username + '!')
    print (username + ',' ,"How do you do?")
In [5]:
name1 = input('Please enter your name : ')
Please enter your name : Ekansh

The name "Guido" is actually stored in name1. So we pass this variable to the function firstfunc() as the variable username because that is the variable that is defined for this function. i.e name1 is passed as username.

In [6]:
firstfunc(name1)
Hey Ekansh!
Ekansh, How do you do?

Let us simplify this even further by defining another function secondfunc() which accepts the name and stores it inside a variable and then calls the firstfunc() from inside the function itself.

In [7]:
def firstfunc(username):
    print ("Hey", username + '!')
    print (username + ',' ,"How do you do?")
def secondfunc():
    name = input("Please enter your name : ")
    firstfunc(name)
In [8]:
secondfunc()
Please enter your name : FoCDoT
Hey FoCDoT!
FoCDoT, How do you do?

Return Statement

When the function results in some value and that value has to be stored in a variable or needs to be sent back or returned for further operation to the main algorithm, return statement is used.

In [9]:
def times(x,y):
    z = x*y
    return z

The above defined times( ) function accepts two arguements and return the variable z which contains the result of the product of the two arguements

In [10]:
c = times(4,5)
print (c)
20

The z value is stored in variable c and can be used for further operations.

Instead of declaring another variable the entire statement itself can be used in the return statement as shown.

In [11]:
def times(x,y):
    '''This multiplies the two input arguments'''
    return x*y
In [12]:
c = times(4,5)
print (c)
20

Since the times( ) is now defined, we can document it as shown above. This document is returned whenever times( ) function is called under help( ) function.

In [13]:
help(times)
Help on function times in module __main__:

times(x, y)
    This multiplies the two input arguments

Multiple variable can also be returned, But keep in mind the order.

In [14]:
eglist = [10,50,30,12,6,8,100]
In [15]:
def egfunc(eglist):
    highest = max(eglist)
    lowest = min(eglist)
    first = eglist[0]
    last = eglist[-1]
    return highest,lowest,first,last

If the function is just called without any variable for it to be assigned to, the result is returned inside a tuple. But if the variables are mentioned then the result is assigned to the variable in a particular order which is declared in the return statement.

In [16]:
egfunc(eglist)
Out[16]:
(100, 6, 10, 100)
In [17]:
a,b,c,d = egfunc(eglist)
print (' a =',a,'\n b =',b,'\n c =',c,'\n d =',d)
 a = 100 
 b = 6 
 c = 10 
 d = 100

Implicit arguments

When an argument of a function is common in majority of the cases or it is "implicit" this concept is used.

In [18]:
def implicitadd(x,y=3):
    return x+y

implicitadd( ) is a function accepts two arguments but most of the times the first argument needs to be added just by 3. Hence the second argument is assigned the value 3. Here the second argument is implicit.

Now if the second argument is not defined when calling the implicitadd( ) function then it considered as 3.

In [19]:
implicitadd(4)
Out[19]:
7

But if the second argument is specified then this value overrides the implicit value assigned to the argument

In [20]:
implicitadd(4,4)
Out[20]:
8

Any number of arguments

If the number of arguments that is to be accepted by a function is not known then a asterisk symbol is used before the argument.

In [21]:
def add_n(*args):
    res = 0
    reslist = []
    for i in args:
        reslist.append(i)
    print (reslist)
    return sum(reslist)

The above function accepts any number of arguments, defines a list and appends all the arguments into that list and return the sum of all the arguments.

In [22]:
add_n(1,2,3,4,5)
[1, 2, 3, 4, 5]
Out[22]:
15
In [23]:
add_n(1,2,3)
[1, 2, 3]
Out[23]:
6

Global and Local Variables

Whatever variable is declared inside a function is local variable and outside the function in global variable.

In [24]:
eg1 = [1,2,3,4,5]

In the below function we are appending a element to the declared list inside the function. eg2 variable declared inside the function is a local variable.

In [25]:
def egfunc1():
    def thirdfunc(arg1):
        eg2 = arg1[:]
        eg2.append(6)
        print ("This is happening inside the function :", eg2 )
    print ("This is happening before the function is called : ", eg1)
    thirdfunc(eg1)
    print ("This is happening outside the function :", eg1)   
    print ("Accessing a variable declared inside the function from outside :" , eg2)
In [26]:
egfunc1()
This is happening before the function is called :  [1, 2, 3, 4, 5]
This is happening inside the function : [1, 2, 3, 4, 5, 6]
This is happening outside the function : [1, 2, 3, 4, 5]
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
<ipython-input-26-a0aede218e7c> in <module>()
----> 1 egfunc1()

<ipython-input-25-dbbddcd9765b> in egfunc1()
      7     thirdfunc(eg1)
      8     print ("This is happening outside the function :", eg1)
----> 9     print ("Accessing a variable declared inside the function from outside :" , eg2)

NameError: name 'eg2' is not defined

If a global variable is defined as shown in the example below then that variable can be called from anywhere.

In [27]:
eg3 = [1,2,3,4,5]
In [28]:
def egfunc1():
    def thirdfunc(arg1):
        global eg2
        eg2 = arg1[:]
        eg2.append(6)
        print ("This is happening inside the function :", eg2 )
    print ("This is happening before the function is called : ", eg1)
    thirdfunc(eg1)
    print( "This is happening outside the function :", eg1 )  
    print ("Accessing a variable declared inside the function from outside :" , eg2)
In [29]:
egfunc1()
This is happening before the function is called :  [1, 2, 3, 4, 5]
This is happening inside the function : [1, 2, 3, 4, 5, 6]
This is happening outside the function : [1, 2, 3, 4, 5]
Accessing a variable declared inside the function from outside : [1, 2, 3, 4, 5, 6]

Lambda Functions

These are small functions which are not defined with any name and carry a single expression whose result is returned. Lambda functions comes very handy when operating with lists. These function are defined by the keyword lambda followed by the variables, a colon and the respective expression.

In [30]:
z = lambda x: x * x
In [31]:
z(8)
Out[31]:
64

map

map( ) function basically executes the function that is defined to each of the list's element separately.

In [32]:
list1 = [1,2,3,4,5,6,7,8,9]
In [33]:
eg = map(lambda x:x+2, list1)
print (list(eg))
[3, 4, 5, 6, 7, 8, 9, 10, 11]

You can also add two lists.

In [34]:
list2 = [9,8,7,6,5,4,3,2,1]
In [35]:
eg2 = list(map(lambda x,y:x+y, list1,list2))
eg2
Out[35]:
[10, 10, 10, 10, 10, 10, 10, 10, 10]

Not only lambda function but also other built in functions can also be used.

In [36]:
eg3 = map(str,eg2)
list(eg3)
Out[36]:
['10', '10', '10', '10', '10', '10', '10', '10', '10']

filter

filter( ) function is used to filter out the values in a list. Note that filter() function returns the result in a new list.

In [37]:
list1 = [1,2,3,4,5,6,7,8,9]

To get the elements which are less than 5,

In [38]:
list(filter(lambda x:x<5,list1))
Out[38]:
[1, 2, 3, 4]

Notice what happens when map() is used.

In [39]:
list(map(lambda x:x<5, list1))
Out[39]:
[True, True, True, True, False, False, False, False, False]

We can conclude that, whatever is returned true in map( ) function that particular element is returned when filter( ) function is used.

In [40]:
list(filter(lambda x:x%4==0,list1))
Out[40]:
[4, 8]