Python Virtual Training For Arcesium - Module II - Day 4

Dec 17-23, 2020 Vikrant Patil

These notes are available online at http://notes.pipal.in/2020/arcesium_finop_batch3/module2-day4.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-day4.ipynb for today's session. Before you start shutdown all kernels except today's notebook.

Problem Implement a class for Stock which should have methods and data encapsulation as given below

``` Stock +--------------------+ | name |----------> update_value | value | | high | | low | +--------------------+ | | | | | | | +-------- get_name | | +------------- get_value | +----------------- get_high +--------------------- get_low

In [1]:
class Stock:
    
    def __init__(self, name, value, high, low):
        self.name = name
        self.value = value
        self.high = high
        self.low = low
        
        
    def update_value(self, value):
        self.value = value
        if value < self.low:
            self.low = value
        if value > self.high:
            self.high = value
            
    def get_name(self):
        return self.name
    
    def get_value(self):
        return self.value
    
    def get_high(self):
        return self.high
    
    def get_low(self):
        return self.low
    
In [3]:
hcl = Stock("HCL", 250.0, 255.4, 200.0)
In [4]:
hcl
Out[4]:
<__main__.Stock at 0x7fc414f987f0>
In [5]:
hcl
Out[5]:
<__main__.Stock at 0x7fc414f987f0>
In [6]:
print(hcl)
<__main__.Stock object at 0x7fc414f987f0>
In [7]:
class Stock:
    
    def __init__(self, name, value, high, low):
        self.name = name
        self.value = value
        self.high = high
        self.low = low
        
        
    def update_value(self, value):
        self.value = value
        if value < self.low:
            self.low = value
        if value > self.high:
            self.high = value
            
    def get_name(self):
        return self.name
    
    def get_value(self):
        return self.value
    
    def get_high(self):
        return self.high
    
    def get_low(self):
        return self.low
    
    def __repr__(self):
        return "Stock(" + self.name + ")"
In [8]:
infy = Stock("Infy", 1500.5, 1500, 1499.0)
In [39]:
infy # this will whatever __repr__ returns
Out[39]:
Stock(Infy)
In [11]:
print(infy)
Stock(Infy)
In [25]:
class Stock:
    
    def __init__(self, name, value, high, low):
        self.name = name
        self.value = value
        self.high = high
        self.low = low
        
        
    def update_value(self, value):
        self.value = value
        if value < self.low:
            self.low = value
        if value > self.high:
            self.high = value
            
    def get_name(self):
        return self.name
    
    def get_value(self):
        return self.value
    
    def get_high(self):
        return self.high
    
    def get_low(self):
        return self.low
    
    def __repr__(self): ## methods that start with __ and ends with __ , are special methods and they are predefined
        return "Stock(" + self.name + ")"
    
    def __str__(self):
        return "Stock<" + ",".join([self.name , str(self.value), str(self.high), str(self.low)]) + ">"
In [22]:
s = Stock("TATA", 150.4, 155.3, 149.0)
In [23]:
s
Out[23]:
Stock(TATA)
In [24]:
print(s)
Stock<TATA,150.4,155.3,149.0>
In [26]:
Stock("HCL", 1, 2, 1)
Out[26]:
Stock(HCL)
In [40]:
numbers = [1, 2, 3]
In [42]:
numbers
Out[42]:
[1, 2, 3]
In [43]:
str(3)
Out[43]:
'3'
In [44]:
str(s)
Out[44]:
'Stock<TATA,150.4,155.3,149.0>'

String Formatting

In [ ]:
 
In [27]:
"Stock({})".format("HCL")
Out[27]:
'Stock(HCL)'
In [28]:
class WellFormattedStock(Stock):
    
    def __repr__(self):
        return "Stock({})".format(self.name)
In [29]:
WellFormattedStock("XYZ", 2, 3, 2)
Out[29]:
Stock(XYZ)
In [30]:
class WellFormattedStock(Stock):
    
    def __repr__(self):
        return "Stock({})".format(self.name)
    
    def __str__(self):
        return "Stock<{}, {}, {}, {}>".format(self.name, self.value, self.high, self.low)
In [31]:
j = WellFormattedStock("JHJH", 2, 3, 2)
In [32]:
j
Out[32]:
Stock(JHJH)
In [33]:
print(j)
Stock<JHJH, 2, 3, 2>
In [35]:
"I can define a string with variable like this {}, which can be filled programticaly using format {}".format("python", 42)
Out[35]:
'I can define a string with variable like this python, which can be filled programticaly using format 42'
In [37]:
"I can also control the order like this {1}, {2}, {0}".format("zeroth", "first", "second")
Out[37]:
'I can also control the order like this first, second, zeroth'
In [38]:
variable = "Arcesium"
"This is fixed sentence with a name in it!".replace("name", variable)
Out[38]:
'This is fixed sentence with a Arcesium in it!'
In [45]:
"One can give variables in format method {} {} {}".format(1, 2, 3)
Out[45]:
'One can give variables in format method 1 2 3'
In [46]:
"{0} One can give {2} ordered variables {1}".format("one", "two", "three")
Out[46]:
'one One can give three ordered variables two'
In [47]:
def add(x, y):
    return x+y
In [48]:
add(3, 4)
Out[48]:
7
In [49]:
add(x=3, y=4)
Out[49]:
7
In [50]:
add(y=4, x=3)
Out[50]:
7
In [51]:
max(["one", "two", "three"], key=len)
Out[51]:
'three'
In [53]:
for i in range(1, 11):
    print("{unit} {sqr} {cube}".format(unit=i, sqr=i*i, cube=i*i*i))
1 1 1
2 4 8
3 9 27
4 16 64
5 25 125
6 36 216
7 49 343
8 64 512
9 81 729
10 100 1000
In [59]:
for i in range(1, 11):
    print(str(i).rjust(2), str(i*i).rjust(3), str(i**3).rjust(4))
 1   1    1
 2   4    8
 3   9   27
 4  16   64
 5  25  125
 6  36  216
 7  49  343
 8  64  512
 9  81  729
10 100 1000
In [60]:
for i in range(1, 11):
    print("{unit:2d} {sqr:3d} {cube:4d}".format(unit=i, sqr=i*i, cube=i*i*i))
 1   1    1
 2   4    8
 3   9   27
 4  16   64
 5  25  125
 6  36  216
 7  49  343
 8  64  512
 9  81  729
10 100 1000
In [61]:
for i in range(1, 11):
    print("{x:2d} {sqrx:3d} {cubex:4d}".format(x=i, sqrx=i*i, cubex=i*i*i))
 1   1    1
 2   4    8
 3   9   27
 4  16   64
 5  25  125
 6  36  216
 7  49  343
 8  64  512
 9  81  729
10 100 1000
In [64]:
for i in range(1, 101):
    print(str(i).ljust(3), str(i*i).ljust(5), str(i**3).ljust(7))
1   1     1      
2   4     8      
3   9     27     
4   16    64     
5   25    125    
6   36    216    
7   49    343    
8   64    512    
9   81    729    
10  100   1000   
11  121   1331   
12  144   1728   
13  169   2197   
14  196   2744   
15  225   3375   
16  256   4096   
17  289   4913   
18  324   5832   
19  361   6859   
20  400   8000   
21  441   9261   
22  484   10648  
23  529   12167  
24  576   13824  
25  625   15625  
26  676   17576  
27  729   19683  
28  784   21952  
29  841   24389  
30  900   27000  
31  961   29791  
32  1024  32768  
33  1089  35937  
34  1156  39304  
35  1225  42875  
36  1296  46656  
37  1369  50653  
38  1444  54872  
39  1521  59319  
40  1600  64000  
41  1681  68921  
42  1764  74088  
43  1849  79507  
44  1936  85184  
45  2025  91125  
46  2116  97336  
47  2209  103823 
48  2304  110592 
49  2401  117649 
50  2500  125000 
51  2601  132651 
52  2704  140608 
53  2809  148877 
54  2916  157464 
55  3025  166375 
56  3136  175616 
57  3249  185193 
58  3364  195112 
59  3481  205379 
60  3600  216000 
61  3721  226981 
62  3844  238328 
63  3969  250047 
64  4096  262144 
65  4225  274625 
66  4356  287496 
67  4489  300763 
68  4624  314432 
69  4761  328509 
70  4900  343000 
71  5041  357911 
72  5184  373248 
73  5329  389017 
74  5476  405224 
75  5625  421875 
76  5776  438976 
77  5929  456533 
78  6084  474552 
79  6241  493039 
80  6400  512000 
81  6561  531441 
82  6724  551368 
83  6889  571787 
84  7056  592704 
85  7225  614125 
86  7396  636056 
87  7569  658503 
88  7744  681472 
89  7921  704969 
90  8100  729000 
91  8281  753571 
92  8464  778688 
93  8649  804357 
94  8836  830584 
95  9025  857375 
96  9216  884736 
97  9409  912673 
98  9604  941192 
99  9801  970299 
100 10000 1000000

problem

  • Write function print_triangle which prints a traigle as given below
      *
     * *
    * * *
   * * * *
  * * * * *
In [66]:
2 * 4
Out[66]:
8
In [67]:
str(*)
  File "<ipython-input-67-f8b8bba140e2>", line 1
    str(*)
         ^
SyntaxError: invalid syntax
In [68]:
"*"
Out[68]:
'*'
In [69]:
str(2)
Out[69]:
'2'
In [70]:
str(+)
  File "<ipython-input-70-84d1d973846d>", line 1
    str(+)
         ^
SyntaxError: invalid syntax
In [78]:
"+" # made this string
Out[78]:
'+'
In [76]:
'*'
Out[76]:
'*'
In [77]:
"""multi"""
Out[77]:
'multi'
In [80]:
def print_triangle(n):
    for i in range(n):
        line = " ".join(list("*"*i))
        print(line.center(2*n-1))
In [82]:
print_triangle(10)
                   
         *         
        * *        
       * * *       
      * * * *      
     * * * * *     
    * * * * * *    
   * * * * * * *   
  * * * * * * * *  
 * * * * * * * * * 
In [92]:
def print_triangle(triangle):
    lastline = triangle[-1]
    w = 2*len(lastline)-1
    for line in triangle:
        print(" ".join(line).center(w))

def triangle(n):
    return [list("*"*i) for i in range(1, n+1)]
In [93]:
triangle(5)
Out[93]:
[['*'],
 ['*', '*'],
 ['*', '*', '*'],
 ['*', '*', '*', '*'],
 ['*', '*', '*', '*', '*']]
In [94]:
t = triangle(5)
print_triangle(t)
    *    
   * *   
  * * *  
 * * * * 
* * * * *
In [95]:
print_triangle(triangle(20))
                   *                   
                  * *                  
                 * * *                 
                * * * *                
               * * * * *               
              * * * * * *              
             * * * * * * *             
            * * * * * * * *            
           * * * * * * * * *           
          * * * * * * * * * *          
         * * * * * * * * * * *         
        * * * * * * * * * * * *        
       * * * * * * * * * * * * *       
      * * * * * * * * * * * * * *      
     * * * * * * * * * * * * * * *     
    * * * * * * * * * * * * * * * *    
   * * * * * * * * * * * * * * * * *   
  * * * * * * * * * * * * * * * * * *  
 * * * * * * * * * * * * * * * * * * * 
* * * * * * * * * * * * * * * * * * * *
In [97]:
list("*"*5)
Out[97]:
['*', '*', '*', '*', '*']
In [99]:
def print_triangle(triangle):
    lastline = triangle[-1]
    w = 2*len(lastline)-1
    for line in triangle:
        print(" ".join(list(line)).center(w))

def triangle(n):
    return ["*"*i for i in range(1, n+1)]


triangle(5)
Out[99]:
['*', '**', '***', '****', '*****']
In [100]:
print_triangle(triangle(10))
         *         
        * *        
       * * *       
      * * * *      
     * * * * *     
    * * * * * *    
   * * * * * * *   
  * * * * * * * *  
 * * * * * * * * * 
* * * * * * * * * *

Bonus problem

  • Write a function to generate pascal triangle
    >>> pascal(5)
    [[1],[1,1], [1,2,1],[1,3,3,1],[1,4,6,4,1]]
  • Write a function print_pascal which prints pascal triangle

    >>> print_pascal(pascal(6))
    
               1
             1   1
            1  2  1
          1   3  3  1
        1   4  6   4  1
       1  5  10  10  5  1
In [102]:
"hello".center(20).index("hello")
Out[102]:
7
In [103]:
"hello".center(21).index("hello")
Out[103]:
8
In [105]:
"iiiiiiiiii".center(20)
Out[105]:
'     iiiiiiiiii     '
In [107]:
"iiiiiiiiii".center(20).index("i")
Out[107]:
5
In [108]:
"iiiiiiiiii".center(19)
Out[108]:
'     iiiiiiiiii    '

Working with dictionaries

In [109]:
names = ["APPLE", "IBM", "AT&T", "AGILENT"]
values = [700.5, 300.1, 355.4, 600.2]

stocks = {}
for name, value in zip(names, values):
    stocks[name] = value
In [110]:
stocks
Out[110]:
{'APPLE': 700.5, 'IBM': 300.1, 'AT&T': 355.4, 'AGILENT': 600.2}
In [111]:
nums = [1, 2, 34]
In [113]:
nums = [1, 2, 3, 4,5 ,6, 7, 8, 90]
sqr = []
for n in nums:
    sqr.append(n*n)
In [114]:
sqr
Out[114]:
[1, 4, 9, 16, 25, 36, 49, 64, 8100]
In [115]:
[n*n for n in nums]
Out[115]:
[1, 4, 9, 16, 25, 36, 49, 64, 8100]
In [116]:
names = ["APPLE", "IBM", "AT&T", "AGILENT"]
values = [700.5, 300.1, 355.4, 600.2]

stocks = {}
for name, value in zip(names, values):
    stocks[name] = value
In [117]:
{name:value for name, value in zip(names, values)}
Out[117]:
{'APPLE': 700.5, 'IBM': 300.1, 'AT&T': 355.4, 'AGILENT': 600.2}
In [118]:
dict(zip(names, values))
Out[118]:
{'APPLE': 700.5, 'IBM': 300.1, 'AT&T': 355.4, 'AGILENT': 600.2}
In [120]:
currency_rate = 1.2
{name:value*currency_rate for name, value in zip(names, values)}
Out[120]:
{'APPLE': 840.6, 'IBM': 360.12, 'AT&T': 426.47999999999996, 'AGILENT': 720.24}
In [121]:
dict(zip(names, values))
Out[121]:
{'APPLE': 700.5, 'IBM': 300.1, 'AT&T': 355.4, 'AGILENT': 600.2}
In [122]:
stocks
Out[122]:
{'APPLE': 700.5, 'IBM': 300.1, 'AT&T': 355.4, 'AGILENT': 600.2}
In [123]:
stocks['APPLE']
Out[123]:
700.5
In [124]:
for key in stocks:
    print(key)
APPLE
IBM
AT&T
AGILENT
In [125]:
for key in stocks:
    print(key, stocks[key])
APPLE 700.5
IBM 300.1
AT&T 355.4
AGILENT 600.2
In [126]:
[value for value in stocks.values()]
Out[126]:
[700.5, 300.1, 355.4, 600.2]
In [127]:
for value in stocks.values():
    print(value)
700.5
300.1
355.4
600.2
In [128]:
for key, value in stocks.items():
    print(key, value)
APPLE 700.5
IBM 300.1
AT&T 355.4
AGILENT 600.2
In [129]:
stocks['MIRCROSOFT']
---------------------------------------------------------------------------
KeyError                                  Traceback (most recent call last)
<ipython-input-129-a63105dda943> in <module>
----> 1 stocks['MIRCROSOFT']

KeyError: 'MIRCROSOFT'
In [130]:
stocks.get('MICROSOFT', 0)
Out[130]:
0
In [131]:
stocks
Out[131]:
{'APPLE': 700.5, 'IBM': 300.1, 'AT&T': 355.4, 'AGILENT': 600.2}
In [133]:
stocks.get("APPLE", 0)
Out[133]:
700.5
In [134]:
stocks
Out[134]:
{'APPLE': 700.5, 'IBM': 300.1, 'AT&T': 355.4, 'AGILENT': 600.2}
In [135]:
stocks.setdefault("MICROSOFT", 0)
Out[135]:
0
In [136]:
stocks
Out[136]:
{'APPLE': 700.5, 'IBM': 300.1, 'AT&T': 355.4, 'AGILENT': 600.2, 'MICROSOFT': 0}
In [138]:
stocks
Out[138]:
{'APPLE': 700.5, 'IBM': 300.1, 'AT&T': 355.4, 'AGILENT': 600.2, 'MICROSOFT': 0}
In [139]:
len(stocks)
Out[139]:
5
In [141]:
{key:value for key,value in stocks.items() if value>400} # get stocks with value > 400
Out[141]:
{'APPLE': 700.5, 'AGILENT': 600.2}
In [142]:
handpicked_stocks = {"APPLE", "IBM"}
In [143]:
{key:value for key, value in stocks.items() if key in handpicked_stocks}
Out[143]:
{'APPLE': 700.5, 'IBM': 300.1}
In [145]:
{key:stocks[key] for key in handpicked_stocks} # this will fail if key in handpicked in not there in stocks
Out[145]:
{'IBM': 300.1, 'APPLE': 700.5}

Example

In [146]:
%%file words.txt
one
one two
one two three
one two three four
one two three four five
one two three four five six
one two three four five seven
one two three four eight seven
one two three nine eight seven
one two ten nine eight seven
one ten nine eight seven
ten nine eight seven
ten nine eight
ten nine
ten
Writing words.txt
In [147]:
def get_words(filename):
    with open(filename) as f:
        return f.read().split()


def word_freq(words):
    freq = {}
    for w in words:
        if w in freq:
            freq[w] += 1
        else:
            freq[w] = 1
    return freq
    
In [148]:
words= get_words("words.txt")
In [149]:
word_freq(words)
Out[149]:
{'one': 11,
 'two': 9,
 'three': 7,
 'four': 5,
 'five': 3,
 'six': 1,
 'seven': 6,
 'eight': 6,
 'nine': 6,
 'ten': 6}
In [154]:
def word_freq1(words):
    freq = {}
    for w in words:
        freq[w] = freq.get(w, 0) + 1  
    return freq
    
In [155]:
word_freq1(words)
Out[155]:
{'one': 11,
 'two': 9,
 'three': 7,
 'four': 5,
 'five': 3,
 'six': 1,
 'seven': 6,
 'eight': 6,
 'nine': 6,
 'ten': 6}
In [156]:
def word_freq2(words):
    freq = {}
    unique = set(words)
    for w in unique:
        freq[w] = words.count(w)

    return freq
In [157]:
word_freq2(words)
Out[157]:
{'one': 11,
 'eight': 6,
 'seven': 6,
 'ten': 6,
 'six': 1,
 'three': 7,
 'five': 3,
 'four': 5,
 'two': 9,
 'nine': 6}
In [158]:
freq = word_freq(words)
In [159]:
for w, count in freq.items():
    print(w, count)
one 11
two 9
three 7
four 5
five 3
six 1
seven 6
eight 6
nine 6
ten 6
In [160]:
def get_value(t):
    return t[1]
    
for w, count in sorted(freq.items(), key=get_value):
    print(w, count)
six 1
five 3
four 5
seven 6
eight 6
nine 6
ten 6
three 7
two 9
one 11
In [161]:
def get_value(t):
    return t[1]
    
for w, count in sorted(freq.items(), key=get_value, reverse=True):
    print(w, count)
one 11
two 9
three 7
seven 6
eight 6
nine 6
ten 6
four 5
five 3
six 1
In [162]:
for w, count in sorted(freq.items(), key=get_value, reverse=True):
    print(w.rjust(5), count)
  one 11
  two 9
three 7
seven 6
eight 6
 nine 6
  ten 6
 four 5
 five 3
  six 1
In [164]:
for w, count in sorted(freq.items(), key=get_value, reverse=True):
    print(w.rjust(5), str(count).rjust(2), "*"*count)
  one 11 ***********
  two  9 *********
three  7 *******
seven  6 ******
eight  6 ******
 nine  6 ******
  ten  6 ******
 four  5 *****
 five  3 ***
  six  1 *
In [ ]: