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 [ ]: