0% found this document useful (0 votes)
3 views

Lecture_Notes_On_Functions

The document provides a comprehensive overview of defining and using functions in Python, including examples of function calls, keyword arguments, and the effects of mutable and immutable objects. It explains scope resolution, the use of global and nonlocal keywords, and demonstrates how to handle default and variable arguments. Additionally, it illustrates how functions can be passed as parameters and the implications of changes made to variables within function contexts.

Uploaded by

pardhapradeep824
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
3 views

Lecture_Notes_On_Functions

The document provides a comprehensive overview of defining and using functions in Python, including examples of function calls, keyword arguments, and the effects of mutable and immutable objects. It explains scope resolution, the use of global and nonlocal keywords, and demonstrates how to handle default and variable arguments. Additionally, it illustrates how functions can be passed as parameters and the implications of changes made to variables within function contexts.

Uploaded by

pardhapradeep824
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 14

Functions

Define a function to add two numbers and call the function.

In [1]: # defining a function


def add(x,y):
z=x+y
return z

# calling a function
a=10
b=20
c = add(a,b)
print("Sum is:",c)

Sum is: 30

call a function using keyword arguments

In [2]: # defining a function


def add(x,y):
z=x+y
return z

a1=23
a2=45
c1 = add(y=a2,x=a1) # you can pass in any order.key must match with formal parameter
print("calling keyword arguments. Sum is:",c1)

calling keyword arguments. Sum is: 68


function to demo: Changes made to immutable objects (numbers, strings,tuples,bool,etc.) inside a
function will be lossed once the function returns (Call By value semantics). In Python every thing is an
object. The variables are references/pointers to the objects. When function call is made the references
to the actual value objects are copied to the formal parameters(reference). Any change made to the
formal reference/address will be effective till the function is executing. Once the function returns formal
references will no longer exist.

In [3]: def change(x,y,z,q):


x=x+1 # number
y=y+"abc" #string
z=(1,'c','k')
q=False
print("\nWithin Function:",x,y,z,q)

a = 20
b = "TestString"
c = (2,3,'abc')
d=True

print("\nBefore change call:a={} b={} c={} d={}".format(a,b,c,d))
change(a,b,c,d)
print("\nAfter change call:a={} b={} c={} d={}".format(a,b,c,d))

Before change call:a=20 b=TestString c=(2, 3, 'abc') d=True

Within Function: 21 TestStringabc (1, 'c', 'k') False

After change call:a=20 b=TestString c=(2, 3, 'abc') d=True

Changing references to other objects with in a function will not have any effect on the actual parameters
passed to the function. Formal parameter references no longer exist once the function returns to its
caller. This is true for all objects (immutable and mutable objects).

In [4]: def changeCompleteReference(l,s,d):


l=['changed'] # changing a list reference to a new list
s={'mango'} # changing a set reference to a new set
d={"k1":"NewValue2"} # changing a dictionary reference to a newa dictionary.
print("\n\nInside changeCompleteReference function:list1=",l,"s={} d={}".format(s

list1 = ['a','b','c']
d={'k1':'OldValue'}
s = {'apple','banana'}

print("\nBefore the function call:list1=",list1,"s={} d={}".format(s,d))
changeCompleteReference(list1,s,d)
print("\n\nAfter the function call:list1={} s={} d={}".format(list1,s,d))

Before the function call:list1= ['a', 'b', 'c'] s={'banana', 'apple'} d={'k1': 'Ol
dValue'}

Inside changeCompleteReference function:list1= ['changed'] s={'mango'} d={'k1': 'N


ewValue2'}

After the function call:list1=['a', 'b', 'c'] s={'banana', 'apple'} d={'k1': 'OldV
alue'}
Formal parameters refering to mutable objects and using the formal parameter, methods are invoked to
change the state of the mutable objects.

Changes made to the membership of a list, set, and dictionary are still visible after returning from the
functions.

In [5]: def change2(l,s,d):


l[1]='changed' # changing a list element
s.add("Mango") # adding a element to set
d["k1"]="NewValue2" # changing value of a key in a dictionary.

list1 = ['a','b','c']
d={'k1':'OldValue'}
s = {'apple','banana'}

print("Before change2 call:list1=",list1,"s={} d={}".format(s,d))
change2(list1,s,d)
print("After change2 call:list1={} s={} d={}".format(list1,s,d))

Before change2 call:list1= ['a', 'b', 'c'] s={'banana', 'apple'} d={'k1': 'OldValu
e'}
After change2 call:list1=['a', 'changed', 'c'] s={'banana', 'Mango', 'apple'} d=
{'k1': 'NewValue2'}

frozenset() can be used to convert a mutable to immutable This function takes input as any iterable
object(list, set, dictionary, etc.) and converts them into immutable object. The order of element is not
guaranteed to be preserved.
In [6]: def change2(l,s,d):
l[1]='changed' # changing a list element
s.add("Mango") # adding a element to set
d["k1"]="NewValue2" # changing value of a key in a dictionary.

list1 = ['a','b','c']
d={'k1':'OldValue'}
s = {'apple','banana'}

print("Before change2 call:list1=",list1,"s={} c={} d={}".format(list1,s,d))
change2(frozenset(list1),s,d)
print("After change2 call:list1={} s={} c={} d={}".format(list1,s,d))

Before change2 call:list1= ['a', 'b', 'c'] s=['a', 'b', 'c'] c={'banana', 'apple'}
d={'k1': 'OldValue'}

---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
Input In [6], in <cell line: 12>()
9 s = {'apple','banana'}
11 print("Before change2 call:list1=",list1,"s={} c={} d={}".format(list1,s,
d))
---> 12 change2(frozenset(list1),s,d)
13 print("After change2 call:list1={} s={} c={} d={}".format(list1,s,d))

Input In [6], in change2(l, s, d)


1 def change2(l,s,d):
----> 2 l[1]='changed' # changing a list element
3 s.add("Mango") # adding a element to set
4 d["k1"]="NewValue2"

TypeError: 'frozenset' object does not support item assignment

define a function that uses default arguments

In [7]: def add3(x,y=3):


z=x+y
return z

a=10
c = add3(a) #using default arg 3 for second parameter
print("add3 Sum is:",c)

#call that uses all the arguments
a1=23
a2=45
c1 = add3(a1,a2) #also can be called with all arguments
print("add3 Sum is:",c1)

add3 Sum is: 13


add3 Sum is: 68

Default arguments should follow non-default arguments


In [8]: def add3Parameters(x, y=3,z=4):
z2=x+y+z
return z2

a=10
b=20
c =30
d = add3Parameters(a,b,c)
print("add3 Sum is:",d)

add3 Sum is: 60

In [9]: def add3Parameters(x,y=3,z=4,q):


z2=x+y+z
return z2

a=10
b=20
c=30
d = add3Parameters(a,b,c) #ambiguity
print("add3 Sum is:",d)

Input In [9]
def add3Parameters(x,y=3,z=4,q):
^
SyntaxError: non-default argument follows default argument

define a function that uses variable arguments

In [10]: def add(*x):


s=0.0
for i in x:
s = s+i
return s

print("Adding four numbers:",add()) # calling with no arguments
print("Adding four numbers:",add(5)) # calling with one arguments
print("Adding four numbers:",add(5,3,8,9)) # calling with 4 arguments
print("Adding three numbers:",add(5,3,8)) # calling with 3 arguments

Adding four numbers: 0.0


Adding four numbers: 5.0
Adding four numbers: 25.0
Adding three numbers: 16.0

In [11]: def f(*x):


for i in x:
print(i)

f(1,'abc') # calling with 2 arguments

1
abc

Variable Key-Value based arguments.


In [12]: def f2(**x):
for i in x:
print(i,x[i])

f2(city="Vizag", name="Vikas",age=25) # calling with 3 arguments

city Vizag
name Vikas
age 25


define a function that demos scope: global, local
Scope resolution: Local(L), Enclosed(E), Global(G), Built-in(B)
keywords: N/A, nonlocal, global, None(imported from a module)

In a function, a varible is only referred (but not modified) runtime looks for
its value in its enclosed context (all the way upto global level). The global
keyword is not mandatory.

In a function, a varible is assigned a value (before it ever referred in the
context) it will be treated like a local varible.

If we want to make changes to a global varible,closest enclosed variable
then use global, nonlocal keyword respectively.

In [13]: pi2 = 'global pi2 variable' #global variable


def inner2():
print(pi2) # just referred(But Not modified) a varible.

inner2()
print(pi2)

global pi2 variable


global pi2 variable

In [14]: pi = 'global pi variable' #global variable


def inner1():
pi = 'inner pi variable' #assigning a value implies it is a local variable
print(pi)

inner1()
print(pi)

inner pi variable
global pi variable

Referecing followed by assigning gives an error (without global keyword )


In [15]: pi = 'global pi variable' #global variable
def inner1():

print(pi)
pi = 'inner pi variable' # Changes the global variable value.
print(pi)

inner1()
print("After the function Call, The value is:",pi)

---------------------------------------------------------------------------
UnboundLocalError Traceback (most recent call last)
Input In [15], in <cell line: 8>()
5 pi = 'inner pi variable' # Changes the global variable value.
6 print(pi)
----> 8 inner1()
9 print("After the function Call, The value is:",pi)

Input In [15], in inner1()


2 def inner1():
----> 4 print(pi)
5 pi = 'inner pi variable' # Changes the global variable value.
6 print(pi)

UnboundLocalError: local variable 'pi' referenced before assignment

When global keyword is used, no local variable is created. Any changes made will be visible after the
call (The changes were made to the global variable)

In [16]: pi = 'global pi variable' #global variable


def inner1():
global pi # global keyword is used. The variable used will be be global variab
print(pi)
pi = 'inner pi variable' # Changes the global variable value.
print(pi)

inner1()
print("After the function Call, The value is:",pi)

global pi variable
inner pi variable
After the function Call, The value is: inner pi variable

Enclosed Scope: Example 1


In [17]: pi = 'global pi variable'

def outer():
pi = 'outer pi variable' # a local variable in the context of outer function crea

def inner():
pi = 'inner pi variable' # a local variable in the context of inner function
print(pi) #uses only inner variable defined

inner()
print(pi) #uses the local variable variable defined in the outer function

outer()
print(pi)

inner pi variable
outer pi variable
global pi variable

Enclosed Scope: Example 2

In [18]: pi = 'global pi variable'

def outer():
pi = 'outer pi variable'

def inner():
print(pi) # Only referred the variable: Uses one of the closest enclosed valu

inner()

outer()
print(pi)

outer pi variable
global pi variable
In [19]: pi = 'global pi variable'

def outer():
pi = 'outer pi variable'

def inner():
print(pi) # referred the variable.
pi="Changed in inner." # attempting to modify the variable.
inner()

outer()
print(pi)

---------------------------------------------------------------------------
UnboundLocalError Traceback (most recent call last)
Input In [19], in <cell line: 11>()
8 pi="Changed in inner." # attempting to modify the variable.
9 inner()
---> 11 outer()
12 print(pi)

Input In [19], in outer()


7 print(pi) # referred the variable.
8 pi="Changed in inner." # attempting to modify the variable.
----> 9 inner()

Input In [19], in outer.<locals>.inner()


6 def inner():
----> 7 print(pi) # referred the variable.
8 pi="Changed in inner."

UnboundLocalError: local variable 'pi' referenced before assignment

Enclosed Scope: Example 3

In [20]: pi = 'global pi variable'

def outer():
pi = 'outer pi variable'
def inner():
nonlocal pi # uses one of the closest enclosed value
print("In Inner Before the Change:",pi)
pi="New value changed inside inner."
print("In Inner function:",pi)
inner()
print("In Outer function:",pi)

outer()
print(pi)

In Inner Before the Change: outer pi variable


In Inner function: New value changed inside inner.
In Outer function: New value changed inside inner.
global pi variable

Enclosed Scope: Example 4


In [21]: pi = 'global pi variable'

def outer():
pi = 'outer pi variable'
def inner():
global pi

print("In Inner Before the Change:",pi)


pi="New value changed inside inner."
print("In Inner After the change:",pi)
inner()
print("In Outer function:",pi)
outer()
print("At the Top Level:",pi)

In Inner Before the Change: global pi variable


In Inner After the change: New value changed inside inner.
In Outer function: outer pi variable
At the Top Level: New value changed inside inner.

global variable can be defined (first time) in a function. If the global variable does not exists then it will
be added to the global scope.

In [22]: # No global variable pi is defined.



def outer():
pi = 'outer pi variable' # local variable defined in the outer() context
def inner():
global pi

pi="New global value defined in inner."


print("In Inner function:",pi)
inner()
print("In Outer function",pi)
outer()
print("At the Top Level:",pi)

In Inner function: New global value defined in inner.


In Outer function outer pi variable
At the Top Level: New global value defined in inner.

Functions can be passed as parameters.


In [23]: def add(x,y):
return (x+y)

def multiply(x,y):
return (x*y)

def perform(a,b,funname):
return funname(a,b)

x2 = perform(3,5,add)
print("3+5=",x2)

x3 = perform(3,5,multiply)
print("3*5=",x3)

3+5= 8
3*5= 15

Sorting based on value and length

In [24]: cities = ["Delhi","Bangalore", "Chennai", "Vizag"]


s = sorted(cities)
print("Sorted by value:",s)
s2 = sorted(cities,key=len)
print("Sorted by length:",s2)

Sorted by value: ['Bangalore', 'Chennai', 'Delhi', 'Vizag']


Sorted by length: ['Delhi', 'Vizag', 'Chennai', 'Bangalore']

Sorting based on last char.

In [25]: def lastChar(x):


return x[-1]

cities = ["Delhi","Bangalore", "Chennai", "Vizag"]

s2 = sorted(cities,key=lastChar)
print("Sorted by last char:",s2)

Sorted by last char: ['Bangalore', 'Vizag', 'Delhi', 'Chennai']


In [ ]: def sum(*x):
s=0.0
for i in x:
s = s+i
return s

def multiply(*x):
s=1
for i in x:
s = s*i
return s

def apply(f,*x):
return f(*x)

print("Apply sum:",apply(sum,1,2)) # calling with 3 arguments
print("Apply sum:",apply(sum,1,2,3)) # calling with 3 arguments

print("Apply multiply:",apply(multiply,1,2)) # calling multiply with 3 arguments
print("Apply multiply:",apply(multiply,1,2,3)) # calling multiply with 3 arguments

None keyword represents null value.

In [26]: def ad_mayMultiply(a,b,c=None):


if(c is None):
return a+b
else:
return (a+b)*c

print("Value:",ad_mayMultiply(2,3,5))
print("Value:",ad_mayMultiply(2,3))
print("Value:",ad_mayMultiply(2,3,None))

Value: 25
Value: 5
Value: 5

Global variables defined in other modules (other python files) can be imported and used.

In [27]: ​
#%% Import global variables from other module
import config2
print("x=",config2.x)
print("y=",config2.y)
print("z=",config2.z)
q = config2.z
print("value of z=",q)

x= 1
y= 3.5
z= Hello
value of z= Hello

functions defined in other modules (other python files) can be imported and used.
In [28]: import config2

a=5
b=8

z = config2.utilityAdd(a,b)

print("After calling the uitlityAdd z=",z)

After calling the uitlityAdd z= 13

In [29]: from config2 import utilityAdd


a=5
b=8
z = utilityAdd(a,b)

print("After calling the uitlityAdd z=",z)

After calling the uitlityAdd z= 13

Execute python code present is a string.

In [30]: mycode = 'print("hello ")'


code = """
def add(x,y):
return x+y

print('Adding 2 and 3 is: ',add(2,3))
"""
exec(mycode)
exec(code)

hello
Adding 2 and 3 is: 5

In [31]: from time import sleep



for i in range(5):
print("Sleeping 1s")
sleep(1)
print(i)

Sleeping 1s
0
Sleeping 1s
1
Sleeping 1s
2
Sleeping 1s
3
Sleeping 1s
4

random() - Return random number between 0.0 and 1.0 randint(i,j) - - Return random number in the
range[i,j]
In [32]: import random
for i in range(10):
x=random.randint(1,6)
y= random.random()
print(x)
print(y)

1
0.1346371733995949
3
0.5897055963394732
4
0.7623801902918336
3
0.06045381312044262
2
0.1842788452038593
3
0.27167156848688145
6
0.32279058941134775
4
0.4002538390637257
5
0.4915254577800502
5
0.5221524057975635

In [33]: import random



mylist = [1, 2, 3, 4,5,6,7,8,9,10]

for i in range(10):
print(random.choice(mylist))

9
3
5
9
8
3
6
4
4
4

In [ ]: ​

You might also like