Python Virtual Training For Arcesium - Module II - Day 3

Dec 17-23, 2020 Vikrant Patil

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

problems

  1. Write a python script cat.py which mimics uniz command cat. Essentially cat.py should print contents of file to standard output (print statement).
!python3 cat.py zen.txt
The Zen of Python, by Tim Peters

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.
Special cases aren't special enough to break the rules.
Although practicality beats purity.
Errors should never pass silently.
Unless explicitly silenced.
In the face of ambiguity, refuse the temptation to guess.
There should be one-- and preferably only one --obvious way to do it.
Although that way may not be obvious at first unless you're Dutch.
Now is better than never.
Although never is often better than *right* now.
If the implementation is hard to explain, it's a bad idea.
If the implementation is easy to explain, it may be a good idea.
Namespaces are one honking great idea -- let's do more of those!
  1. write a script wc.py which mimics unix command wc. It should print line count, word count and char count and filename.
python3 wc.py zen.txt
21 144 857 zen.txt
  1. Write a function csvparse which will load data from file and create a list as shown below.
file%% data.csv
symbol,day,price
IBM,Monday,111.23
IBM,Tuesday,112.54
APPLE,Monday,200.45
APPLE,Tuesday,205.54

```

csvparse("data.csv") [['IBM', 'Monday', 111.23], ['IBM','Tuesday',112.54], ['APPLE','Monday',200.45] ['APPLE','Tuesday',205.54]]

In [2]:
%%file cat.py
import sys

def cat(filename):
    with open(filename) as f:
        print(f.read()) # this reads comple contents of file in memory
        

if __name__ == "__main__":
    filename = sys.argv[1]
    cat(filename)
Writing cat.py
In [3]:
!python3 cat.py zen.txt
The Zen of Python, by Tim Peters

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.
Special cases aren't special enough to break the rules.
Although practicality beats purity.
Errors should never pass silently.
Unless explicitly silenced.
In the face of ambiguity, refuse the temptation to guess.
There should be one-- and preferably only one --obvious way to do it.
Although that way may not be obvious at first unless you're Dutch.
Now is better than never.
Although never is often better than *right* now.
If the implementation is hard to explain, it's a bad idea.
If the implementation is easy to explain, it may be a good idea.
Namespaces are one honking great idea -- let's do more of those!

In [10]:
%%file head.py
import sys

def head(filename, n):
    with open(filename) as f:
        for i in range(n):
            print(f.readline(), end="")
            
if __name__ == "__main__": ## double underscores to both name as well as for main
    n = int(sys.argv[1]) #text->int
    filename = sys.argv[2]
    head(filename, n)
    
Overwriting head.py
In [7]:
!python3 head.py 3 zen.txt 
The Zen of Python, by Tim Peters

Beautiful is better than ugly.
In [8]:
import this
The Zen of Python, by Tim Peters

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.
Special cases aren't special enough to break the rules.
Although practicality beats purity.
Errors should never pass silently.
Unless explicitly silenced.
In the face of ambiguity, refuse the temptation to guess.
There should be one-- and preferably only one --obvious way to do it.
Although that way may not be obvious at first unless you're Dutch.
Now is better than never.
Although never is often better than *right* now.
If the implementation is hard to explain, it's a bad idea.
If the implementation is easy to explain, it may be a good idea.
Namespaces are one honking great idea -- let's do more of those!
In [9]:
%%file zen.txt
The Zen of Python, by Tim Peters

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.
Special cases aren't special enough to break the rules.
Although practicality beats purity.
Errors should never pass silently.
Unless explicitly silenced.
In the face of ambiguity, refuse the temptation to guess.
There should be one-- and preferably only one --obvious way to do it.
Although that way may not be obvious at first unless you're Dutch.
Now is better than never.
Although never is often better than *right* now.
If the implementation is hard to explain, it's a bad idea.
If the implementation is easy to explain, it may be a good idea.
Namespaces are one honking great idea -- let's do more of those!
Overwriting zen.txt
In [13]:
%%file wc.py
import sys

def line_count(filename):
    with open(filename) as f:
        return len(f.readlines())
    
def word_count(filename):
    with open(filename) as f:
        words = f.read().split() # will take all white spaces- space/tab/newline
        return len(words) 

def char_count(filename):
    with open(filename) as f:
        return len(f.read())
    
    
if __name__ == "__main__":
    f = sys.argv[1]
    print(line_count(f), word_count(f), char_count(f), f)
Overwriting wc.py
In [12]:
!python3 wc.py zen.txt
21 144 857 zen.txt
In [14]:
import wc
In [15]:
wc.line_count("module1-day1_2.ipynb")
Out[15]:
2105
In [16]:
!ls
addall.py  Makefile		     module1-day3.html	 module2-day3.html
add.py	   mean.py		     module1-day3.ipynb  module2-day3.ipynb
cat.py	   module1-assignment.html   module1-day4.html	 module-day5.html
data.txt   module1-assignment.ipynb  module1-day4.ipynb  push
head1.py   module1-day1_2.html	     module1-day5.html	 __pycache__
head2.py   module1-day1_2.ipynb      module1-day5.ipynb  sample.py
head3.py   module1-day1.html	     module2-day1.html	 stats.py
head5.py   module1-day1.ipynb	     module2-day1.ipynb  Untitled.html
head.py    module1-day2.html	     module2-day2.html	 wc.py
hello.py   module1-day2.ipynb	     module2-day2.ipynb  zen.txt
In [17]:
!pwd
/home/vikrant/trainings/2020/arcesium_finop_batch3
In [19]:
%%file data.csv
symbol,day,price
IBM,Monday,111.23
IBM,Tuesday,112.54
APPLE,Monday,200.45
APPLE,Tuesday,205.54
Writing data.csv
In [26]:
%%file parsecsvdata.py

def csvparse(filename):
    with open(filename) as f:
        heder = f.readline() # read header
        data = []
        for line in f: # f is iterator , so it understands where the current position is
            fields = line.split(",")
            data.append(fields)
        return data
            
Overwriting parsecsvdata.py
In [24]:
import parsecsvdata # will import only once
In [25]:
parsecsvdata.csvparse("data.csv")
Out[25]:
[['IBM', 'Monday', '111.23\n'],
 ['IBM', 'Tuesday', '112.54\n'],
 ['APPLE', 'Monday', '200.45\n'],
 ['APPLE', 'Tuesday', '205.54\n']]
In [27]:
%%file parsecsvdata1.py

def csvparse(filename):
    with open(filename) as f:
        heder = f.readline() # read header
        data = []
        for line in f: # f is iterator , so it understands where the current position is
            fields = line.strip().split(",")
            data.append(fields)
        return data
Writing parsecsvdata1.py
In [30]:
import parsecsvdata1
In [31]:
parsecsvdata1.csvparse("data.csv")
Out[31]:
[['IBM', 'Monday', '111.23'],
 ['IBM', 'Tuesday', '112.54'],
 ['APPLE', 'Monday', '200.45'],
 ['APPLE', 'Tuesday', '205.54']]
In [34]:
%%file parsecsvdata1.py

def csvparse(filename):
    with open(filename) as f:
        heder = f.readline() # read header
        data = []
        for line in f: # f is iterator , so it understands where the current position is
            fields = line.strip().split(",")
            data.append(fields)
        return data

if __name__ == "__main__":
    print(csvparse("data.csv")) # testing
Overwriting parsecsvdata1.py
In [35]:
def csvparse(filename):
    with open(filename) as f:
        heder = f.readline() # read header
        data = []
        for line in f: # f is iterator , so it understands where the current position is
            fields = line.strip().split(",")
            data.append(fields)
        return data
In [37]:
data = csvparse("data.csv")
In [38]:
data
Out[38]:
[['IBM', 'Monday', '111.23'],
 ['IBM', 'Tuesday', '112.54'],
 ['APPLE', 'Monday', '200.45'],
 ['APPLE', 'Tuesday', '205.54']]
In [39]:
data[0][-1]
Out[39]:
'111.23'
In [43]:
def convert(fields):
    return fields[:2] + [float(fields[-1])]

def csvparse(filename):
    with open(filename) as f:
        heder = f.readline() # read header
        data = []
        for line in f: # f is iterator , so it understands where the current position is
            fields = line.strip().split(",")
            fields = convert(fields)
            data.append(fields)
        return data
In [44]:
csvparse("data.csv")
Out[44]:
[['IBM', 'Monday', 111.23],
 ['IBM', 'Tuesday', 112.54],
 ['APPLE', 'Monday', 200.45],
 ['APPLE', 'Tuesday', 205.54]]
In [45]:
f = open("data.csv")
In [46]:
f.readline()
Out[46]:
'symbol,day,price\n'
In [47]:
f.readline()
Out[47]:
'IBM,Monday,111.23\n'
In [48]:
l = f.readline()
In [49]:
l
Out[49]:
'IBM,Tuesday,112.54\n'
In [50]:
l.split(",")
Out[50]:
['IBM', 'Tuesday', '112.54\n']
In [51]:
l.strip().split(",")
Out[51]:
['IBM', 'Tuesday', '112.54']
In [52]:
f.close()

Writing files

``` ======== =========================================== mode meaning ======== =========================================== w Write, overwrite if file exists a append mode, if file exists ..write to end. rb or b read in binary mode wb write binary mode ab append in binary mode ======== ===========================================

Example

In [54]:
url = "https://raw.githubusercontent.com/vikipedia/python-trainings/master/online_course/source/module2/indexdata.txt"
import requests

def download(url, filename): 
    with open(filename, "wb") as bf:
        r = requests.get(url) 
        bf.write(r.content) 
In [55]:
!python3 -m pip install requests
Requirement already satisfied: requests in /home/vikrant/anaconda3/lib/python3.8/site-packages (2.24.0)
Requirement already satisfied: chardet<4,>=3.0.2 in /home/vikrant/anaconda3/lib/python3.8/site-packages (from requests) (3.0.4)
Requirement already satisfied: urllib3!=1.25.0,!=1.25.1,<1.26,>=1.21.1 in /home/vikrant/anaconda3/lib/python3.8/site-packages (from requests) (1.25.9)
Requirement already satisfied: certifi>=2017.4.17 in /home/vikrant/anaconda3/lib/python3.8/site-packages (from requests) (2020.6.20)
Requirement already satisfied: idna<3,>=2.5 in /home/vikrant/anaconda3/lib/python3.8/site-packages (from requests) (2.10)
WARNING: You are using pip version 20.2.3; however, version 20.3.3 is available.
You should consider upgrading via the '/home/vikrant/anaconda3/bin/python3 -m pip install --upgrade pip' command.
In [56]:
download(url, "indexdata.txt")
In [58]:
!python3 head.py 20 indexdata.txt
symbol
price
change
volume

MJRWW
130.72759478533843
3.694439794801307
3604

RBFER
138.70935284443215
2.216908526674474
1827

NILRA
191.03471832663206
0.4674588939635804
3809

In [61]:
def parseSerialFormat(filename):
    with open(filename) as f:
        tabular = []
        row = []
        for line in f:
            item = line.strip()
            if item=="":
                tabular.append(row) # this makes it 2D data
                row = []
            else:
                row.append(item)
        if row:
            tabular.append(row)
    return tabular
                
In [62]:
parseSerialFormat("indexdata.txt")
Out[62]:
[['symbol', 'price', 'change', 'volume'],
 ['MJRWW', '130.72759478533843', '3.694439794801307', '3604'],
 ['RBFER', '138.70935284443215', '2.216908526674474', '1827'],
 ['NILRA', '191.03471832663206', '0.4674588939635804', '3809'],
 ['KLAUL', '171.8732962407023', '3.3674773238125804', '4930'],
 ['NSDQL', '115.53093172800759', '2.9539737397625716', '3046'],
 ['IIJCO', '132.72824504260913', '2.0073130063688', '2311'],
 ['RFGYO', '165.16558643307485', '4.298006358962731', '214'],
 ['ISUBX', '163.00760618033004', '0.04753420473903924', '2903'],
 ['JSFNB', '162.7964294777765', '4.468458672093418', '1486'],
 ['XIIHE', '100.1283215847198', '2.4659528050212005', '1866'],
 ['KBNBF', '165.47518316307583', '0.23959575155823087', '3834'],
 ['UMMXP', '109.69660529916302', '3.1912597734501857', '306'],
 ['TKKVO', '144.64943725495849', '4.550962454198143', '2995'],
 ['DEFKM', '183.563134741773', '0.354583080023832', '453'],
 ['DDAUE', '167.43485943165342', '4.462651203629318', '881'],
 ['CABGJ', '182.4185113412454', '0.9893499879911921', '3399'],
 ['VQDKF', '128.7740419792224', '4.040731018215812', '3784'],
 ['WQHNA', '189.2156926901894', '1.6436503299556149', '130'],
 ['DRBWM', '134.7001220983072', '0.3527838213440315', '4449'],
 ['OSTGG', '188.16655957982945', '3.708942762087685', '3490']]
In [63]:
tabdata = parseSerialFormat("indexdata.txt")
In [64]:
def writeCSV(tabular, filename):
    with open(filename, "w") as f:
        for row in tabular:
            f.write(",".join(row))
            f.write("\n")
In [65]:
writeCSV(tabdata, "index.csv")
In [66]:
!python3 head.py 5 index.csv
symbol,price,change,volume
MJRWW,130.72759478533843,3.694439794801307,3604
RBFER,138.70935284443215,2.216908526674474,1827
NILRA,191.03471832663206,0.4674588939635804,3809
KLAUL,171.8732962407023,3.3674773238125804,4930
In [67]:
weeklydata = csvparse("data.csv")
In [68]:
weeklydata
Out[68]:
[['IBM', 'Monday', 111.23],
 ['IBM', 'Tuesday', 112.54],
 ['APPLE', 'Monday', 200.45],
 ['APPLE', 'Tuesday', 205.54]]
In [70]:
writeCSV(weeklydata, "weekly.csv")
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-70-f92c5d2c684f> in <module>
----> 1 writeCSV(weeklydata, "weekly.csv")

<ipython-input-64-1fd7704f9ea6> in writeCSV(tabular, filename)
      2     with open(filename, "w") as f:
      3         for row in tabular:
----> 4             f.write(",".join(row))
      5             f.write("\n")

TypeError: sequence item 2: expected str instance, float found
In [80]:
def writeCSV(tabular, filename):
    with open(filename, "w") as f:
        for row in tabular:
            stritems = [str(item) for item in row]
            f.write(",".join(stritems))
            f.write("\n")
In [72]:
writeCSV(weeklydata, "weekly.csv")
In [73]:
!cat weekly.csv
IBM,Monday,111.23
IBM,Tuesday,112.54
APPLE,Monday,200.45
APPLE,Tuesday,205.54
In [74]:
writeCSV(tabdata, "index.csv")
In [75]:
!cat index.csv
symbol,price,change,volume
MJRWW,130.72759478533843,3.694439794801307,3604
RBFER,138.70935284443215,2.216908526674474,1827
NILRA,191.03471832663206,0.4674588939635804,3809
KLAUL,171.8732962407023,3.3674773238125804,4930
NSDQL,115.53093172800759,2.9539737397625716,3046
IIJCO,132.72824504260913,2.0073130063688,2311
RFGYO,165.16558643307485,4.298006358962731,214
ISUBX,163.00760618033004,0.04753420473903924,2903
JSFNB,162.7964294777765,4.468458672093418,1486
XIIHE,100.1283215847198,2.4659528050212005,1866
KBNBF,165.47518316307583,0.23959575155823087,3834
UMMXP,109.69660529916302,3.1912597734501857,306
TKKVO,144.64943725495849,4.550962454198143,2995
DEFKM,183.563134741773,0.354583080023832,453
DDAUE,167.43485943165342,4.462651203629318,881
CABGJ,182.4185113412454,0.9893499879911921,3399
VQDKF,128.7740419792224,4.040731018215812,3784
WQHNA,189.2156926901894,1.6436503299556149,130
DRBWM,134.7001220983072,0.3527838213440315,4449
OSTGG,188.16655957982945,3.708942762087685,3490
In [78]:
",".join(weeklydata[0])
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-78-bf84ac59ddc2> in <module>
----> 1 ",".join(weeklydata[0])

TypeError: sequence item 2: expected str instance, float found
In [79]:
",".join(  [ str(item) for item in  weeklydata[0]])
Out[79]:
'IBM,Monday,111.23'
In [84]:
def parseSerialFormat(filename):
    with open(filename) as f:
        tabular = []
        row = []
        for line in f:
            item = line.strip()
            if item=="":
                tabular.append(row) # this makes it 2D data
                row = []
            else:
                row.append(item)
        #if row: # this takes care of last set of values where empty line will not come after it, instead file will end
        #    tabular.append(row)
    return tabular
                
In [83]:
parseSerialFormat("indexdata.txt")
Out[83]:
[['symbol', 'price', 'change', 'volume'],
 ['MJRWW', '130.72759478533843', '3.694439794801307', '3604'],
 ['RBFER', '138.70935284443215', '2.216908526674474', '1827'],
 ['NILRA', '191.03471832663206', '0.4674588939635804', '3809'],
 ['KLAUL', '171.8732962407023', '3.3674773238125804', '4930'],
 ['NSDQL', '115.53093172800759', '2.9539737397625716', '3046'],
 ['IIJCO', '132.72824504260913', '2.0073130063688', '2311'],
 ['RFGYO', '165.16558643307485', '4.298006358962731', '214'],
 ['ISUBX', '163.00760618033004', '0.04753420473903924', '2903'],
 ['JSFNB', '162.7964294777765', '4.468458672093418', '1486'],
 ['XIIHE', '100.1283215847198', '2.4659528050212005', '1866'],
 ['KBNBF', '165.47518316307583', '0.23959575155823087', '3834'],
 ['UMMXP', '109.69660529916302', '3.1912597734501857', '306'],
 ['TKKVO', '144.64943725495849', '4.550962454198143', '2995'],
 ['DEFKM', '183.563134741773', '0.354583080023832', '453'],
 ['DDAUE', '167.43485943165342', '4.462651203629318', '881'],
 ['CABGJ', '182.4185113412454', '0.9893499879911921', '3399'],
 ['VQDKF', '128.7740419792224', '4.040731018215812', '3784'],
 ['WQHNA', '189.2156926901894', '1.6436503299556149', '130'],
 ['DRBWM', '134.7001220983072', '0.3527838213440315', '4449']]

Classes and OOPS

Lets take simple example of implemeting code for bank account

In [86]:
%%file bank0.py

balance = 0

def deposit(amount):
    global balance # don't make a local variable... it is global variable
    balance += amount
    
def withdraw(amount):
    global balance
    balance -= amount
    
def get_balance():
    return balance


if __name__ == "__main__":
    pass # empty statement
Overwriting bank0.py
In [87]:
import bank0
In [88]:
bank0.get_balance()
Out[88]:
0
In [89]:
bank0.deposit(42000)
In [90]:
bank0.get_balance()
Out[90]:
42000
In [91]:
bank0.withdraw(2344)
In [92]:
bank0.get_balance()
Out[92]:
39656
In [93]:
l = []
In [94]:
l.append(1)
In [95]:
l
Out[95]:
[1]
In [116]:
%%file bank2.py

def create_account(balance=0):
    return {"balance":balance}

def deposit(account, amount):
    account['balance'] += amount
    
def withdraw(account, amount):
    if account['balance'] > amount:
        account['balance'] -= amount
    
def get_balance(account):
    return account['balance']

if __name__ == "__main__":
    pass
Overwriting bank2.py
In [112]:
import bank2
In [113]:
a1 = bank2.create_account(100)
In [114]:
a2 = bank2.create_account()
In [115]:
bank2.get_balance(a1)
Out[115]:
100
In [117]:
bank2.get_balance(a2)
Out[117]:
0
In [118]:
bank2.deposit(a1, 424242)
In [119]:
bank2.deposit(a2, 42000)
In [120]:
bank2.get_balance(a1)
Out[120]:
424342
In [121]:
bank2.get_balance(a2)
Out[121]:
42000
In [122]:
bank2.withdraw(a1, 4543)
In [123]:
bank2.get_balance(a1)
Out[123]:
419799
In [124]:
del bank1
In [125]:
class BankAccount:
    
    def __init__(self, balance=0): # we these functions as methods
        self.balance = balance
        
    def deposit(self, amount):
        self.balance += amount
        
    def withdraw(self, amount):
        if self.balance >= amount:
            self.balance -= amount
            
    def get_balance(self):
        return self.balance
In [126]:
BankAccount
Out[126]:
__main__.BankAccount
In [127]:
b1 = BankAccount(100) # this will call __init__
In [128]:
b1
Out[128]:
<__main__.BankAccount at 0x7f5b993779a0>
In [130]:
b1.deposit(2000)
In [131]:
b1.get_balance()
Out[131]:
2100
In [132]:
b1.withdraw(20)
In [133]:
b1.get_balance()
Out[133]:
2080
In [134]:
b2 = BankAccount()
In [135]:
b2.get_balance()
Out[135]:
0
In [136]:
l = list("thres")
In [137]:
l
Out[137]:
['t', 'h', 'r', 'e', 's']
In [138]:
l = list((1, 2, 3, 4))
In [139]:
l
Out[139]:
[1, 2, 3, 4]
In [140]:
b1
Out[140]:
<__main__.BankAccount at 0x7f5b993779a0>
Instance of class
+-----------------+
|                 | <------------methods to manipulate data
|  data           | <------------ method
|                 |
+-----------------+
      |
      +----------------->----- method to access data

     Light
   +--------------+
   |              |<---------- switch_on
   |   on=True    |
   |              |<---------- switch_off
   +--------------+
         |
         +-------------->--- is_on

 `
In [141]:
class Light:
    
    def __init__(self):
        self.on  = False
        
    def switch_on(self):
        self.on = True
        
    def switch_off(self):
        self.on = False
        
    def is_on(self):
        return self.on
    
    def toggle(self):
        if self.on:
            self.switch_off()
        else:
            self.switch_on()
In [1]:
l1 = Light() # this will call __init__ method from class Light
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
<ipython-input-1-2412d9a7d1c1> in <module>
----> 1 l1 = Light() # this will call __init__ method from class Light

NameError: name 'Light' is not defined
In [143]:
l1.is_on()
Out[143]:
False
In [144]:
l1.switch_on()
In [145]:
l1.is_on()
Out[145]:
True
In [148]:
class WhiteLight:
    
    color = "white" # class variable
    
    def __init__(self):
        self.on  = False
        
    def switch_on(self):
        self.on = True
        
    def switch_off(self):
        self.on = False
        
    def is_on(self):
        return self.on
    
    def toggle(self):
        if self.on:
            self.switch_off()
        else:
            self.switch_on()
In [149]:
w1 = WhiteLight()
w2 = WhiteLight()
In [150]:
w1.is_on()
Out[150]:
False
In [151]:
w1.switch_on()
In [152]:
w1.is_on()
Out[152]:
True
In [153]:
w2.is_on()
Out[153]:
False
In [154]:
w1.color
Out[154]:
'white'
In [155]:
w2.color
Out[155]:
'white'
In [156]:
WhiteLight.color
Out[156]:
'white'
In [157]:
WhiteLight.on
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-157-bc6550f2e318> in <module>
----> 1 WhiteLight.on

AttributeError: type object 'WhiteLight' has no attribute 'on'
In [158]:
w1.on
Out[158]:
True
In [159]:
w2.on
Out[159]:
False
In [160]:
WhiteLight.color = "Tinted White"
In [161]:
WhiteLight.color
Out[161]:
'Tinted White'
In [162]:
w1.color
Out[162]:
'Tinted White'
In [163]:
w2.color
Out[163]:
'Tinted White'
In [164]:
w1.color
Out[164]:
'Tinted White'

Inheritance

In [166]:
class GreenLight(Light): # in bracker we specify parent class
    color = "green"
In [167]:
g1 = GreenLight()
In [168]:
g1.switch_on()
In [169]:
g1.is_on()
Out[169]:
True
In [170]:
g1.color
Out[170]:
'green'
In [171]:
type("tyter")
Out[171]:
str
In [172]:
isinstance(g1, GreenLight)
Out[172]:
True
In [173]:
isinstance(g1, Light)
Out[173]:
True

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