Python Virtual Training For Arcesium - Module II - Day 1

Dec 17-23, 2020 Vikrant Patil

These notes are available online at http://notes.pipal.in/2020/arcesium_finop_batch3/module2-day1.html

© Pipal Academy LLP

Day 1 | Day 2 | Day 3 | Day 4 | Day 5

We will be using jupyter hub from http://lab.pipal.in for this training. Create a notebook with name module2-day1.ipynb for today's session.

Quick recap of loops

In [1]:
collection = ["Hello", "world", 1, 2, 3, 4]
for item in collection:
    print(item, end=",")
Hello,world,1,2,3,4,
In [2]:
for c in "on text data":
    print(c,end=",")
o,n, ,t,e,x,t, ,d,a,t,a,
In [3]:
person = {"name":"Alice", "email":"alice@wonder.land"}

for key in person:
    print(key, person[key])
name Alice
email alice@wonder.land
In [6]:
nums = {1, 2, 3, 4, 5, 5, 6, 6} # unique
In [5]:
for item in nums:# set
    print(item)
1
2
3
4
5
6
In [7]:
def unique(items):
    return set(items) # this will return set (which is uniqe), but order is not gauranteed!
In [8]:
unique([1, 1, 1, 2, 3, 1, 2])
Out[8]:
{1, 2, 3}
In [9]:
nums = range(5) # this will have nmbers from 0 to 4
In [10]:
for i in nums:
    print(i)
0
1
2
3
4
In [11]:
for i in range(5):
    print(i, end=",")
0,1,2,3,4,
In [12]:
for i in range(4, -1, -1):
    print(i, end=',')
4,3,2,1,0,
In [21]:
words = ["one", "two", "three", "four", "five"]
for w in words: # for loop syntax
    print(w, end=",")
one,two,three,four,five,
In [14]:
for w in reversed(words): # will allow us to go through the collection in reversed fashion
    print(w, end=",")
five,four,three,two,one,
In [15]:
reversedlist = reversed(words) # should not be done
In [19]:
for w in reversedlist:# puting for loop in reversed iterator only once is possible
    print(w, end=",")
In [18]:
for w in reversedlist:
    print(w, end=",") # it will not print anything!
In [20]:
for w in reversed(words):
    print(w, end=",")
five,four,three,two,one,
In [24]:
i = 0
for x in [1, 2, 3, 4, 5]:
    print("iteration", i)
    print("value of x", x)
    i = i +1
iteration 0
value of x 1
iteration 1
value of x 2
iteration 2
value of x 3
iteration 3
value of x 4
iteration 4
value of x 5
In [25]:
for w in ["one", "two", "three", "four"]:
    print(w)
one
two
three
four
In [26]:
words = ["one", "two", "three", "four"]

for word in words:
    print(word)
one
two
three
four
In [27]:
for i in reversed(range(5)):
    print(i, end=",")
4,3,2,1,0,
In [28]:
poem = """Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
Complex is better than complicated.
Flat is better than nested.
Sparse is better than dense.
Readability counts.
"""
In [30]:
for line in poem.split("\n"):
    print(line)
Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
Complex is better than complicated.
Flat is better than nested.
Sparse is better than dense.
Readability counts.

In [31]:
for line in poem.split("."):
    print(line)
Beautiful is better than ugly

Explicit is better than implicit

Simple is better than complex

Complex is better than complicated

Flat is better than nested

Sparse is better than dense

Readability counts


In [32]:
for line in reversed(poem.split("\n")):
    print(line)
Readability counts.
Sparse is better than dense.
Flat is better than nested.
Complex is better than complicated.
Simple is better than complex.
Explicit is better than implicit.
Beautiful is better than ugly.
In [33]:
for i in range(5):
    print(i, end=",")
0,1,2,3,4,
In [34]:
for i in reversed(range(5)):
    print(i, end=",")
4,3,2,1,0,
In [37]:
lines = poem.strip().split("\n")
In [38]:
lines
Out[38]:
['Beautiful is better than ugly.',
 'Explicit is better than implicit.',
 'Simple is better than complex.',
 'Complex is better than complicated.',
 'Flat is better than nested.',
 'Sparse is better than dense.',
 'Readability counts.']
In [39]:
for line in lines:
    print(line)
Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
Complex is better than complicated.
Flat is better than nested.
Sparse is better than dense.
Readability counts.
In [40]:
for line in reversed(lines):
    print(line)
Readability counts.
Sparse is better than dense.
Flat is better than nested.
Complex is better than complicated.
Simple is better than complex.
Explicit is better than implicit.
Beautiful is better than ugly.
In [42]:
for index, value in enumerate(lines):
    print(index, value)
0 Beautiful is better than ugly.
1 Explicit is better than implicit.
2 Simple is better than complex.
3 Complex is better than complicated.
4 Flat is better than nested.
5 Sparse is better than dense.
6 Readability counts.
In [53]:
words = ["one", "two", "three", "four", "five"] # stored by location .. by index
for word in words: # allows going over items directly accesing index!
    print(word, end=",")
    
print()
    
for index, word in enumerate(words):
    print(index, word)
one,two,three,four,five,
0 one
1 two
2 three
3 four
4 five
In [56]:
for word in words:
    print(words.index(word), word) # this time consuming O(N^2)
0 one
1 two
2 three
3 four
4 five
In [47]:
def printwith_linenums(poem):
    lines = poem.strip().split("\n")
    for i, line in enumerate(lines, start=1):
        print(i, line)
In [48]:
printwith_linenums(poem)
1 Beautiful is better than ugly.
2 Explicit is better than implicit.
3 Simple is better than complex.
4 Complex is better than complicated.
5 Flat is better than nested.
6 Sparse is better than dense.
7 Readability counts.
In [54]:
firstname = ["Alice", "Elsa", "Alex", "Elisa"]
lastname = ["Wondegirl", "Frozen", "Lion", "Hacker"]

for i, name in enumerate(firstname):
    print(i, name, lastname[i])
0 Alice Wondegirl
1 Elsa Frozen
2 Alex Lion
3 Elisa Hacker
In [50]:
for name, last in zip(firstname, lastname):
    print(name, last)
Alice Wondegirl
Elsa Frozen
Alex Lion
Elisa Hacker
In [59]:
xs = ["x1", "x2", "x3", "x4"]
ys = ["y1", "y2", "y3", "y4"]
zs = ["z1", "z2", "z3", "z5"]
In [62]:
for x, y, z in zip(xs, ys, zs): # zip can take multiple list as argument
    print(x, y, z)
x1 y1 z1
x2 y2 z2
x3 y3 z3
x4 y4 z5
In [61]:
print(1, 2, 3, 4, 5)
1 2 3 4 5
In [64]:
xs = ["one", "two", "three"]
nums = (1, 2, 3, 4, 5)
In [65]:
for n, x in zip(nums, xs):
    print(n, x)
1 one
2 two
3 three
In [67]:
xs = ["one", "two", "three"]
nums = (1, 2, 3)
for n, x in reversed(zip(nums, xs)):
    print(n, x)
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-67-82bab2c934c0> in <module>
      1 xs = ["one", "two", "three"]
      2 nums = (1, 2, 3)
----> 3 for n, x in reversed(zip(nums, xs)):
      4     print(n, x)

TypeError: 'zip' object is not reversible
In [68]:
xs = ["one", "two", "three"]
nums = (1, 2, 3)
for n, x in zip(reversed(nums), reversed(xs)):
    print(n, x)
3 three
2 two
1 one
In [70]:
for i, values in enumerate(zip(nums, xs)):
    print(i, values)
0 (1, 'one')
1 (2, 'two')
2 (3, 'three')
In [71]:
for i, values in reversed(zip(nums, xs)):
    print(i, values)
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-71-1abe3ee5308e> in <module>
----> 1 for i, values in reversed(zip(nums, xs)):
      2     print(i, values)

TypeError: 'zip' object is not reversible
In [72]:
for i, n, x in enumerate(zip(nums, xs)):
    print(i, n, x)
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-72-066d64fd8e86> in <module>
----> 1 for i, n, x in enumerate(zip(nums, xs)):
      2     print(i, n, x)

ValueError: not enough values to unpack (expected 3, got 2)
In [73]:
list(zip(nums, xs))
Out[73]:
[(1, 'one'), (2, 'two'), (3, 'three')]
In [74]:
nums
Out[74]:
(1, 2, 3)
In [75]:
xs
Out[75]:
['one', 'two', 'three']
In [77]:
list(zip(nums, xs))
Out[77]:
[(1, 'one'), (2, 'two'), (3, 'three')]
In [82]:
zipped = zip(nums, xs)
In [83]:
for item in zipped: # it also an iterator
    print(item)
(1, 'one')
(2, 'two')
(3, 'three')
In [84]:
for item in zipped:
    print(item)
In [85]:
nums = [1, 2, 3, 4]
In [102]:
niter = iter(nums) # for loop internally works on iterators
In [88]:
next(niter)
Out[88]:
1
In [90]:
next(niter)
Out[90]:
2
In [91]:
next(niter)
Out[91]:
3
In [92]:
next(niter)
Out[92]:
4
In [93]:
next(niter)
---------------------------------------------------------------------------
StopIteration                             Traceback (most recent call last)
<ipython-input-93-b38c395f3c33> in <module>
----> 1 next(niter)

StopIteration: 
In [94]:
for n in nums:
    print(n)
1
2
3
4
In [95]:
enums = enumerate(nums)
In [96]:
enums
Out[96]:
<enumerate at 0x7f880ed88200>
In [97]:
next(enums)
Out[97]:
(0, 1)
In [98]:
next(enums)
Out[98]:
(1, 2)
In [99]:
next(enums)
Out[99]:
(2, 3)
In [100]:
next(enums)
Out[100]:
(3, 4)
In [101]:
next(enums)
---------------------------------------------------------------------------
StopIteration                             Traceback (most recent call last)
<ipython-input-101-f0ad7538fd93> in <module>
----> 1 next(enums)

StopIteration: 
In [103]:
printwith_linenums(poem)
1 Beautiful is better than ugly.
2 Explicit is better than implicit.
3 Simple is better than complex.
4 Complex is better than complicated.
5 Flat is better than nested.
6 Sparse is better than dense.
7 Readability counts.
In [104]:
printwith_linenums(poem)
1 Beautiful is better than ugly.
2 Explicit is better than implicit.
3 Simple is better than complex.
4 Complex is better than complicated.
5 Flat is better than nested.
6 Sparse is better than dense.
7 Readability counts.
In [105]:
for i in reversed(nums):
    print(i)
4
3
2
1
In [106]:
r = reversed(nums) #here iterartor got created

for i in r: # 
    print(i) # it got consumed
    
for i in r:
    print(i)#??? nothing , its already consumed
    
for i in reversed(nums): # cretaed
    print(i) # consumed
4
3
2
1
4
3
2
1
In [107]:
r = reversed(nums) # never store it like this!!! use it directly in for loop


def print_items(items):
    print("started")
    for i in items:
        print(i)
    print("ended")
    
print_items(r)
print_items(r)
started
4
3
2
1
ended
started
ended
In [108]:
for i in reversed(nums):
    print(i)
4
3
2
1
In [110]:
x = 10 # it is not an iterator

Problems

  • Write a function vector_add which does vector addition of two vectors taken as a list
>>> vector_add([1, 1, 1], [3 , 4, 5])
[4, 5, 6]
  • A matrix is called as unit matrix if all elements except diagonal elements in every row are 0 and dialgonal elements are 1. Write a function to check if given matrix is unit matrix or not?
>>> m = [[1, 0, 0, 0],
         [0, 1, 0, 0],
         [0, 0, 1, 0],
         [0, 0, 0, 1]]
>>> is_unit_matrix(m)
True

>>> is_unit_matrix([[1,2],[2,1]])
False
  • bonus problem- There are two lists
>>> a = [1, 2, 3]
>>> b = ['a', 'b', 'c']

Write a functio merge whcih will merge the lists into a single list such that alternatively one item from first list and one item from second list is taken.

>>> merge(a, b)
[1, 'a', 2, 'b', 3, 'c']
In [111]:
def vector_add(vector1, vector2):
    result = []
    for v1, v2 in zip(vector1, vector2):
        result.append(v1+v2)
    
    return result 
In [112]:
vector_add([1, 1, 1], [3, 4, 5])
Out[112]:
[4, 5, 6]
In [113]:
vector_add([2, 3, 4], [2, 2, 2])
Out[113]:
[4, 5, 6]
In [124]:
m = [[1, 0, 0, 0],
         [0, 1, 0, 0],
         [0, 0, 1, 0],
         [0, 0, 0, 1]]


#for row in m:
#    print(row)
    
    
    
def is_unit_matrix(mat):
    for i, row in enumerate(mat):
        if row[i]!=1 or sum(row)!=1:
            return False

    return True
    

is_unit_matrix(m)

m1 = [[1, 1, 1],
      [0, 1, 1],
      [0, 0, 1]]

is_unit_matrix(m1)

m2 = [[1, -2, 2],
      [0,  1, 0],
      [0 , 0, 1]]
is_unit_matrix(m2)
Out[124]:
True
In [125]:
def zeros_except_diagonal(row, rowindex):
    for i, item in enumerate(row):
        if i!=rowindex and item!=0:
            return False
    
    return True
    
def is_unit_matrix(mat):
    for i, row in enumerate(mat):
        if row[i]!=1 or not zeros_except_diagonal(row,i):
            return False

    return True
In [126]:
is_unit_matrix(m2)
Out[126]:
False
In [127]:
is_unit_matrix(m1)
Out[127]:
False
In [128]:
is_unit_matrix(m)
Out[128]:
True
In [129]:
2*3
Out[129]:
6
In [130]:
2*3
5*6
Out[130]:
30
In [132]:
2*4
5*3
5**5 # only repr of last line will be shown
Out[132]:
3125

List comprehensions

In [137]:
def findlens(words):
    """
    compute length of every word
    word1 -> len(word1)
    word2 -> len(word2)
    word3 -> len(word3)
    """
    lens = []
    for word in words:
        lens.append(len(word))
    return lens


def squares(nums):
    """
    compute square of every item
    n1  -> n1*n1
    n2  -> n2*n2
    n3  -> n3*n3
    n4  -> n4*n4
    """
    sqrs = []
    for n in nums:
        sqrs.append(n*n)
    return sqrs
In [138]:
words= "Hello make some words out of this text".split()
In [139]:
words
Out[139]:
['Hello', 'make', 'some', 'words', 'out', 'of', 'this', 'text']
In [140]:
findlens(words)
Out[140]:
[5, 4, 4, 5, 3, 2, 4, 4]
In [141]:
nums = [2, 3, 1, 4, 5]
In [142]:
squares(nums)
Out[142]:
[4, 9, 1, 16, 25]

these are some examples of mappings!

List1      result
 ||          ||

item1  -> do_operation(item1)
item2  -> do_operation(item2)
item3  -> do_operation(item3)
item4  -> do_operation(item4)
In [143]:
[len(word) for word in words]
Out[143]:
[5, 4, 4, 5, 3, 2, 4, 4]
In [144]:
[x*x for x in nums]
Out[144]:
[4, 9, 1, 16, 25]
In [145]:
[x*x*x for x in nums]
Out[145]:
[8, 27, 1, 64, 125]
In [146]:
def findlens(words):
    return [len(w) for w in words]


def squares(numbers):
    return [n*n for n in numbers]


def cubes(nums):
    return [x*x*x for x in nums]
In [147]:
def evens(nums):
    e = []
    for n in nums:
        if n%2==0:
            e.append(n)
    return e
In [148]:
evens([1, 2, 12, 12, 2, 3, 4, 5, 6, 7, 5, 7, 5])
Out[148]:
[2, 12, 12, 2, 4, 6]
In [149]:
def find_words_of_len(words, l):
    words_of_len = []
    for w in words:
        if len(w)==l:
            words_of_len.append(w)
    return words_of_len
In [151]:
find_words_of_len(words, 4)
Out[151]:
['make', 'some', 'this', 'text']
In [157]:
[n for n in nums if n%2==0] # filtering
Out[157]:
[2, 4]
In [156]:
[w for w in words if len(w)==4] # filtering operation
Out[156]:
['make', 'some', 'this', 'text']
In [155]:
[n*n for n in nums if n%2==0] # filtering and mapping
Out[155]:
[4, 16]
In [158]:
def even(x):
    return x%2==0
In [159]:
even(3)
Out[159]:
False
In [161]:
even(2)
Out[161]:
True
In [162]:
[n for n in nums if even(n)]
Out[162]:
[2, 4]
In [163]:
[n*n for n in nums if even(n)]
Out[163]:
[4, 16]

Problems

  • write function listpy (just like os.listdir!) which uses list comprehension to identify py files in given directory.:
    >>> listpy(os.getcwd())
    add.py
    add1.py
    add2.py
    hello.py
  • find sum of all multiples of 7 or 11 below 1000.
  • There is a string "abrakadabra", we want to capitalize alternate character from it. how can we do it? can a list comprehension be used to do this?
  • Some records are stored with timestamp in database as shown below.:
    records = [("2018-11-11 24:04","11803","16602"),
                ("2018-11-11 24:09","11782","16568"),
                ("2018-11-11 24:14","11741","16524"),
                ("2018-11-11 24:19","11756","16543"),
                ("2018-11-11 24:24","11741","16538"),
                ("2018-11-11 24:28","11722","16558"),
                ("2018-11-11 24:34","11716","16457"),
                ("2018-11-11 24:39","11724","16430"),
                ("2018-11-11 24:44","11723","16572"),
                ("2018-11-11 24:49","11739","16611"),
                ("2018-11-11 24:54","11740","16501"),
                ("2018-11-11 24:58","11743","16568"),
                ("2018-11-12 01:04","11754","16626")]

The timestamp given above has been misprinted, instead of 11th Nov 24:04 , it should be 12 Nov 00:04! Write a function to correct the record. use list comprehension to do this.

  • Write a function factors which finds all factors of given number (include 1 and self)
  • Write a function is_prime which checks if given number is prime based on fact that prime number has only two factors 1 and self.
  • Write a list comprehension to generate prime numbers.

Bonus Problem

  • Implement excel function COUNTIFS as a function in python. COUNTIFS(criteria_list, condition). Here first argument is the list on which count will be performed. Second argument is condition as a string , as in excel.
        "<" --------- less than
        "<="--------- less than or equal to
        ">" --------- greater than
        ">="--------- greater than or equal to
        "<>"--------- not equal to

    Sample run is shown below:

    >>> a = [10,20,30,40,50,40,40,50]
    >>> COUNTIFS(a, "<40")
    3
    >>> COUNTIFS(a, ">=40")
    5
    >>> COUNTIFS(a, "40")
    >>> COUNTIFS(a, "<>40")
    5
In [ ]: