Sep 20-24, 2021 Vikrant Patil
These notes are available online at https://notes.pipal.in/2021/arcesium_finop_batch2/
© Pipal Academy LLP
Day 1 | Day 2 | Day 3 | Day 4 | Day 5
We will be using jupyter hub from https://lab2.pipal.in for this training.
login to hub and create a notebook with name module1-day3
def twice(x):
print(2*x)
def funcname(parameters):
return parameters**2
def twice(x):
# note that there is no return statement
print(2*x)
twice(twice(twice(5)))
10
--------------------------------------------------------------------------- TypeError Traceback (most recent call last) <ipython-input-4-f7a610c3ddfc> in <module> ----> 1 twice(twice(twice(5))) <ipython-input-3-8db4314a5c52> in twice(x) 1 def twice(x): ----> 2 print(2*x) TypeError: unsupported operand type(s) for *: 'int' and 'NoneType'
r = twice(5)
print("*"*5, r) # whenever does not have return statement, by default it returns None
10 ***** None
None + 1
--------------------------------------------------------------------------- TypeError Traceback (most recent call last) <ipython-input-9-3fd8740bf8ab> in <module> ----> 1 None + 1 TypeError: unsupported operand type(s) for +: 'NoneType' and 'int'
None * 2
--------------------------------------------------------------------------- TypeError Traceback (most recent call last) <ipython-input-10-60f90da77edb> in <module> ----> 1 None * 2 TypeError: unsupported operand type(s) for *: 'NoneType' and 'int'
twice(twice(twice(5)))
twice(twice(None))
def twice1(x):
return 2*x
twice1(twice1(twice1(5)))
40
2 + 3
2*3
2**3
8
print(2+3)
print(2*3)
print(2**3)
5 6 8
x = 2+3
y = 2*3
z = 2**3
print(x, y, z)
5 6 8
m = print(2+3)
n = print(2*3)
k = print(2**3)
5 6 8
print(m , n, k) # print function does not return any value
None None None
def twice1(x):
return 2*x
twice1(5)
twice1(10)
twice1(20)
40
def twice1(x):
return 2*x
print(twice1(5))
print(twice1(10))
print(twice1(20))
10 20 40
def function_with_multiple_returns(a,b):
return a+b # the moment return is executed ...function is over ..it returns to place from where it was called!
return a*b
function_with_multiple_returns(2, 3)
5
def function_that_returns_multiple_objects(a, b):
return a+b, a*b # if return statement has multiple objects..those will be received as tuple
function_that_returns_multiple_objects(3, 4)
(7, 12)
result = function_that_returns_multiple_objects(3, 4)
result
(7, 12)
result[0]
7
result[1]
12
x, y = 2, 4 # you can do multiple assignments in single statement
first, last = "vikrant", "patil"
first
'vikrant'
last
'patil'
addtion, multiplication = function_that_returns_multiple_objects(3, 4)
addtion
7
multiplication
12
def compound_interest(P, r, n, t):
return p*(1+r/n)**(n*t)
compound_interest(25000, 0.07, 4, 5)
--------------------------------------------------------------------------- NameError Traceback (most recent call last) <ipython-input-44-b20cc0c37f88> in <module> ----> 1 compound_interest(25000, 0.07, 4, 5) <ipython-input-43-4c16406d2046> in compound_interest(P, r, n, t) 1 def compound_interest(P, r, n, t): ----> 2 return p*(1+r/n)**(n*t) NameError: name 'p' is not defined
def compound_interest(P, r, n, t):
return P*(1+r/n)**(n*t)
compound_interest(25000, 0.07, 4, 5)
35369.454893894996
compound_interest(25000, 4, 5, 0.007)
25519.640161941425
the order of arguments is important , while calling the function make sure that you pass the arguments in same order as in definition of the function
compound_interest(P=25000, r=0.07, t=5, n=4)
35369.454893894996
compound_interest(r=0.07, t=5, P=25000, n=4)
35369.454893894996
compound_interest(25000, 0.07, n=4, t=5) # positional arguments can be given initially
35369.454893894996
compound_interest(P=25000, 0.07, 4, 5)
File "<ipython-input-51-6f31b60ea1db>", line 1 compound_interest(P=25000, 0.07, 4, 5) ^ SyntaxError: positional argument follows keyword argument
Examples
x
2
del x
x
--------------------------------------------------------------------------- NameError Traceback (most recent call last) <ipython-input-55-6fcf9dfbd479> in <module> ----> 1 x NameError: name 'x' is not defined
x = 10
def foo():
print(x) #?
foo()
10
x = 10
def foo():
x = 20 # assignment operator will create a local variable ...
print("x inside foo:", x)
foo()
print("x outside , after calling foo:", x)
x inside foo: 20 x outside , after calling foo: 10
x = 10
def foo():
x = x + 1 #there is a confit here! creating a local and trying to access global!
foo()
print(x)
--------------------------------------------------------------------------- UnboundLocalError Traceback (most recent call last) <ipython-input-58-f764f6f1287c> in <module> 5 6 ----> 7 foo() 8 print(x) <ipython-input-58-f764f6f1287c> in foo() 2 3 def foo(): ----> 4 x = x + 1 #there is a confit here! creating a local and trying to access global! 5 6 UnboundLocalError: local variable 'x' referenced before assignment
x = [1, 1, 1]
def appendzero(a): # at this point a is pointing to x
a = a + [0] # assignment will create a as local!!
appendzero(x)
print(x)
[1, 1, 1]
x = [1, 1, 1]
def appendzero(a): # at this point a is pointing to x
a.append(0) # this will change the x itself!
appendzero(x)
print(x)
[1, 1, 1, 0]
def add(a, b):
return a+b
x
[1, 1, 1, 0]
add
<function __main__.add(a, b)>
x[1]
1
add(2, 3)
5
alias_add = add
alias_add
<function __main__.add(a, b)>
alias_add(2, 3)
5
x , y = 2, 3
add(x, y)
5
def square(x):
return x*x
def sumofsquares(x, y):
return square(x) + square(y)
def cube(x):
return x*x*x
def sumofcubes(x, y):
return cube(x) + cube(y)
def sumof(x, y, func):
return func(x) + func(y)
sumofsquares(5, 4)
41
sumof(5, 4, square)
41
sumofcubes(5, 4)
189
sumof(5, 4, cube)
189
max([3, 23, 4, 2])
23
max(["one", "two", "three", "four", "five", "six", "seventy"])
'two'
words = ["one", "two", "three", "four", "five", "six", "seventy"]
sorted(words)
['five', 'four', 'one', 'seventy', 'six', 'three', 'two']
max(words) # five , four,
'two'
max(words, key=len) # compare items based on len
'seventy'
def mylen(word):
print("I got word:", word)
return len(word)
max(words, key=mylen)
I got word: one I got word: two I got word: three I got word: four I got word: five I got word: six I got word: seventy
'seventy'
records = [
("TATA", 200.0, 5.5),
("INFY", 2000.0, -5),
("RELIANCE", 1505.5, 50.0),
("HCL", 1200, 70.5)
]
max(records)
('TATA', 200.0, 5.5)
def get_value(record):
return record[1]
def get_gain(record):
return record[2]
max(records, key=get_value)
('INFY', 2000.0, -5)
max(records, key=get_gain)
('HCL', 1200, 70.5)
records[0]
('TATA', 200.0, 5.5)
records[1]
('INFY', 2000.0, -5)
records[2]
('RELIANCE', 1505.5, 50.0)
def get_value(r):
print("argument for key function", r)
print("get_value is returning", r[1])
print("x"*10)
return r[1]
lines = """this is first line
second line
third line
fourth line""".split("\n")
lines
['this is first line', 'second line', 'third line', 'fourth line']
records
[('TATA', 200.0, 5.5),
('INFY', 2000.0, -5),
('RELIANCE', 1505.5, 50.0),
('HCL', 1200, 70.5)]
max(records, key=get_value)
argument for key function ('TATA', 200.0, 5.5)
get_value is returning 200.0
xxxxxxxxxx
argument for key function ('INFY', 2000.0, -5)
get_value is returning 2000.0
xxxxxxxxxx
argument for key function ('RELIANCE', 1505.5, 50.0)
get_value is returning 1505.5
xxxxxxxxxx
argument for key function ('HCL', 1200, 70.5)
get_value is returning 1200
xxxxxxxxxx
('INFY', 2000.0, -5)
min(records, key=get_value)
argument for key function ('TATA', 200.0, 5.5)
get_value is returning 200.0
xxxxxxxxxx
argument for key function ('INFY', 2000.0, -5)
get_value is returning 2000.0
xxxxxxxxxx
argument for key function ('RELIANCE', 1505.5, 50.0)
get_value is returning 1505.5
xxxxxxxxxx
argument for key function ('HCL', 1200, 70.5)
get_value is returning 1200
xxxxxxxxxx
('TATA', 200.0, 5.5)
max(records, key=get_gain)
('HCL', 1200, 70.5)
min(records, key=get_gain)
('INFY', 2000.0, -5)
sorted(records, key=get_gain)
[('INFY', 2000.0, -5),
('TATA', 200.0, 5.5),
('RELIANCE', 1505.5, 50.0),
('HCL', 1200, 70.5)]
sorted(records, key=get_value)
argument for key function ('TATA', 200.0, 5.5)
get_value is returning 200.0
xxxxxxxxxx
argument for key function ('INFY', 2000.0, -5)
get_value is returning 2000.0
xxxxxxxxxx
argument for key function ('RELIANCE', 1505.5, 50.0)
get_value is returning 1505.5
xxxxxxxxxx
argument for key function ('HCL', 1200, 70.5)
get_value is returning 1200
xxxxxxxxxx
[('TATA', 200.0, 5.5),
('HCL', 1200, 70.5),
('RELIANCE', 1505.5, 50.0),
('INFY', 2000.0, -5)]
lines
['this is first line', 'second line', 'third line', 'fourth line']
max(lines, key=len)
'this is first line'
problem
def get_value(record):
return record[1]
def get_gain(record):
return record[2]
get_value(records)
('INFY', 2000.0, -5)
records = [('TATA', 200.0, 5.5),
("MAHINDRA", 150.0, 5.1),
('INFY', 2000.0, -5),
('RELIANCE', 1505.5, 50.0),
('HCL', 1200, 70.5)]
get_value(records) # this is not returning max item but item at index 1
('MAHINDRA', 150.0, 5.1)
def get_word_count(text):
words = text.split()
return len(words)
get_word_count("give me any statement and I will tell you how many words are there")
14
max(lines, key=get_word_count)
'this is first line'
def make_logger(loggername):
def log(message):
print(loggername.upper() + ":", message)
return log # it is returning a function!
info = make_logger("info")
warning = make_logger("warn")
error = make_logger("error")
info
<function __main__.make_logger.<locals>.log(message)>
info("I am staring up...")
INFO: I am staring up...
warning
<function __main__.make_logger.<locals>.log(message)>
warning("There is something wrong with database, retrying!")
WARN: There is something wrong with database, retrying!
error
<function __main__.make_logger.<locals>.log(message)>
error("Doomed! database has failed!")
ERROR: Doomed! database has failed!
def make_logger(loggername): # closure remebers the context like ..loggername variable
def log(message):
print(loggername.upper() + ":", message)
return log # it is returning a function! Whenever you return a fucntion it remebers the context for it.. it is called as closure
info = make_logger("info") # make_logger gets called with parameter loggername="info"
# create a function called log
info("With some info message") # "With some info message" this text goes as message parameter the the function which was defined inside make_logger
INFO: With some info message
def foo():
3 +4
x = x + 6
return x
x = 2 # variable..it has a name
2 # literal...it has a value...no name
2
def foobar():
pass # empty statement
foobar # is something like a variable ... it has a name ..name is foobar
<function __main__.foobar()>
def square(x):
return x*x
lambda x: x*x # is a function ... it has value which contains function object ...but it has no name
<function __main__.<lambda>(x)>
lines
['this is first line', 'second line', 'third line', 'fourth line']
max(lines, key=lambda l: len(l.split())) # find a line with max words
'this is first line'
lambda x: x*x*x # a function that computes cube
<function __main__.<lambda>(x)>
lambda x: x.upper() # a fucntion that makes text to upper case
<function __main__.<lambda>(x)>
f = lambda x: x.upper()
f("some test")
'SOME TEST'
max(records, key= lambda r: r[1])
('INFY', 2000.0, -5)