Python Training at VMWare - Day 3

Jan 17-19, 2018 Vikrant Patil

These notes are available online at http://notes.pipal.in/2018/vmware-jan-python

© Pipal Academy LLP

Day 1 | Day 2 | Day 3

In [19]:
def column(data, c):
    rowcount = len(data)
    return [data[i][c] for i in range(rowcount)]

def reverse(items):
    return list(reversed(items))

def rotate90clockewise(data):
    colcount = len(data[0])
    return [reverse(column(data, i)) for i in range(colcount)]

def transpose(data):
    colcount = len(data[0])
    return [column(data, i) for i in range(colcount)]

def rotate90anticlockwise(data):
    return reverse(transpose(data))
In [20]:
data = [["A1","B1","C1"],
        ["A2","B2","C2"],
        ["A3","B3","C3"]]
In [21]:
transpose(data)
Out[21]:
[['A1', 'A2', 'A3'], ['B1', 'B2', 'B3'], ['C1', 'C2', 'C3']]
In [22]:
rotate90clockewise(data)
Out[22]:
[['A3', 'A2', 'A1'], ['B3', 'B2', 'B1'], ['C3', 'C2', 'C1']]
In [23]:
rotate90anticlockwise(data)
Out[23]:
[['C1', 'C2', 'C3'], ['B1', 'B2', 'B3'], ['A1', 'A2', 'A3']]

Working with files

In [24]:
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 [25]:
%%file data.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!
Writing data.txt
In [29]:
filehandle = open("data.txt")
In [30]:
filehandle.read() #this will read complete file as a string
Out[30]:
"The Zen of Python, by Tim Peters\n\nBeautiful is better than ugly.\nExplicit is better than implicit.\nSimple is better than complex.\nComplex is better than complicated.\nFlat is better than nested.\nSparse is better than dense.\nReadability counts.\nSpecial cases aren't special enough to break the rules.\nAlthough practicality beats purity.\nErrors should never pass silently.\nUnless explicitly silenced.\nIn the face of ambiguity, refuse the temptation to guess.\nThere should be one-- and preferably only one --obvious way to do it.\nAlthough that way may not be obvious at first unless you're Dutch.\nNow is better than never.\nAlthough never is often better than *right* now.\nIf the implementation is hard to explain, it's a bad idea.\nIf the implementation is easy to explain, it may be a good idea.\nNamespaces are one honking great idea -- let's do more of those!"
In [31]:
filehandle.read()
Out[31]:
''
In [32]:
filehandle.close()
In [33]:
filehandle = open("data.txt")
In [34]:
lines = filehandle.readlines()
In [37]:
for line in lines:
    print(line, end="")
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 [38]:
for index,line in enumerate(lines):
    print(index+1, line, end="")
1 The Zen of Python, by Tim Peters
2 
3 Beautiful is better than ugly.
4 Explicit is better than implicit.
5 Simple is better than complex.
6 Complex is better than complicated.
7 Flat is better than nested.
8 Sparse is better than dense.
9 Readability counts.
10 Special cases aren't special enough to break the rules.
11 Although practicality beats purity.
12 Errors should never pass silently.
13 Unless explicitly silenced.
14 In the face of ambiguity, refuse the temptation to guess.
15 There should be one-- and preferably only one --obvious way to do it.
16 Although that way may not be obvious at first unless you're Dutch.
17 Now is better than never.
18 Although never is often better than *right* now.
19 If the implementation is hard to explain, it's a bad idea.
20 If the implementation is easy to explain, it may be a good idea.
21 Namespaces are one honking great idea -- let's do more of those!
In [39]:
filehandle = open("data.txt")
In [40]:
filehandle.readline()
Out[40]:
'The Zen of Python, by Tim Peters\n'
In [41]:
filehandle.readline()
Out[41]:
'\n'
In [42]:
filehandle.readline()
Out[42]:
'Beautiful is better than ugly.\n'
In [44]:
count = 1
line = filehandle.readline()
while line!="":
    print(count, line, end="")
    line = filehandle.readline()
    count += 1
1 Simple is better than complex.
2 Complex is better than complicated.
3 Flat is better than nested.
4 Sparse is better than dense.
5 Readability counts.
6 Special cases aren't special enough to break the rules.
7 Although practicality beats purity.
8 Errors should never pass silently.
9 Unless explicitly silenced.
10 In the face of ambiguity, refuse the temptation to guess.
11 There should be one-- and preferably only one --obvious way to do it.
12 Although that way may not be obvious at first unless you're Dutch.
13 Now is better than never.
14 Although never is often better than *right* now.
15 If the implementation is hard to explain, it's a bad idea.
16 If the implementation is easy to explain, it may be a good idea.
17 Namespaces are one honking great idea -- let's do more of those!

problems

  • Write python script cat.py which implements roughly unix command cat. cat prints all the input files to standard output.
  • Write python script head.py which implements unix command head. it should take number of lines as commmandline argument.
  • Write a python script wc.py which implements unix command wc.
In [45]:
%%file cat.py
"""
cat module implements unix command cat, approximately
"""
import sys

def cat(file):
    """
    print the file to standard output
    """
    for line in open(file):
        print(line, end="")
        
def catfiles(files):
    """
    print multiple files to standard output
    """
    for file in files:
        cat(file)
        
if __name__ == "__main__":
    catfiles(sys.argv[1:])
Writing cat.py
In [46]:
!python cat.py /home/vikrant/programming/explorations/python/argv.py data.txt
import sys

if __name__ == "__main__":
    print(sys.argv)
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 [53]:
%%file head.py
"""
head module implements unix command head approximately
"""
import sys

def head(file, n):
    filehandle = open(file)
    line = filehandle.readline()
    count = 1
    while line and count<=n:
        print(line, end="")
        count += 1
        line = filehandle.readline()
        
if __name__ == "__main__":
    head(sys.argv[1], int(sys.argv[2]))
        
Overwriting head.py
In [54]:
!python head.py data.txt 5
The Zen of Python, by Tim Peters

Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
In [55]:
%%file wc.py
"""
wc module implements unix command wc approximately
"""
import sys

def word_count(file):
    words = open(file).read().split()
    return len(words)

def char_count(file):
    return len(open(file).read())

def line_count(file):
    return len(open(file).readlines())


if __name__ == "__main__":
    file = sys.argv[1]
    print(line_count(file), word_count(file), char_count(file), file)
Writing wc.py
In [56]:
!python wc.py data.txt
21 144 856 data.txt

What about finding file with largest number of line count in current directory?

file with largest number of words?

In [57]:
import os
In [59]:
files = [file for file in os.listdir(os.getcwd()) if os.path.isfile(file)]
In [60]:
files
Out[60]:
['wc.py',
 'push',
 'day1.ipynb',
 'head.py',
 'add.p',
 'myscript.py',
 'links.txt',
 'day2.ipynb',
 'echo.py',
 'day2.html',
 'Untitled.html',
 'links.txt~',
 'hello.py',
 'mymodule.py',
 'hello1.py',
 'moddule1.py',
 'day3.ipynb',
 'functions.py',
 'data.txt',
 'module1.py',
 'module2.py',
 'day3.html',
 'Makefile',
 'add.py',
 'cat.py',
 'day1.html',
 'ls.py']
In [63]:
import wc
count = 0
f = files[0]
for file in files:
    lcount = wc.line_count(file)
    if lcount > count:
        count = lcount
        f = file
print(f, count)
day1.html 22182
In [64]:
max(files, key=wc.line_count)
Out[64]:
'day1.html'
In [65]:
max(files, key=wc.word_count)
Out[65]:
'day1.html'

Writing files

In [66]:
file = open("numbers.txt", "w")
In [67]:
file.write("one\n")
file.write("two\n")
file.write("three\n")
Out[67]:
6
In [68]:
file.close()
In [69]:
!python cat.py numbers.txt
one
two
three
In [74]:
file = open("numbers.txt", "r+") #read and write at a time, but file has to pre-exist.
file.write("1\n")
file.write("2\n")
file.flush()
In [75]:
file.readline()
Out[75]:
'two\n'
In [76]:
file.readline()
Out[76]:
'three\n'
In [77]:
file.readline()
Out[77]:
''
In [78]:
file.close()
In [79]:
!python cat.py numbers.txt
1
2
two
three
In [80]:
file  = open("numbers.txt","a")
file.write("end\n")
Out[80]:
4
In [81]:
file.close()
In [82]:
!python cat.py numbers.txt
1
2
two
three
end
In [83]:
file = open("binary.bin", "wb")
file.write(b"\x65\x69")
file.close()
In [84]:
file = open("binary.bin", "rb")
file.read()
Out[84]:
b'ei'
In [85]:
b = b"binary"
In [86]:
type(b)
Out[86]:
bytes
In [87]:
b.decode()
Out[87]:
'binary'
In [88]:
"string".encode()
Out[88]:
b'string'
In [89]:
file = open("regional.txt", "w", encoding="utf-8")
file.write("हाआ")
file.close()
In [90]:
file = open("regional.txt", encoding="utf-8")
file.read()
Out[90]:
'हाआ'

Examples

  • Write csv files
  • Parse csv files
In [93]:
tables = [[str(i*j) for i in range(1,6)] for j in range(1,11) ]
In [94]:
tables
Out[94]:
[['1', '2', '3', '4', '5'],
 ['2', '4', '6', '8', '10'],
 ['3', '6', '9', '12', '15'],
 ['4', '8', '12', '16', '20'],
 ['5', '10', '15', '20', '25'],
 ['6', '12', '18', '24', '30'],
 ['7', '14', '21', '28', '35'],
 ['8', '16', '24', '32', '40'],
 ['9', '18', '27', '36', '45'],
 ['10', '20', '30', '40', '50']]
In [110]:
def csvwriter(data, filename):
    file = open(filename, "w")
    for row in data:
        file.write(",".join(row))
        file.write("\n")
    file.close()
    

def columndatawriter(data, delimiter, filename):
    with open(filename, "w") as f:
        for row in data:
            f.write(delimiter.join(row))
            f.write("\n")

csvwriter = lambda data, file: columndatawriter(data, ",", file)

def csvwriter(data, file):
    return columndatawriter(data, ",", file)

tsvwriter = lambda data, file: columndatawriter(data, "\t", file)
In [105]:
csvwriter(tables, "tables.csv")
In [106]:
!python cat.py tables.csv
1,2,3,4,5
2,4,6,8,10
3,6,9,12,15
4,8,12,16,20
5,10,15,20,25
6,12,18,24,30
7,14,21,28,35
8,16,24,32,40
9,18,27,36,45
10,20,30,40,50
In [102]:
csvwriter(tables, "tables.csv")
In [107]:
!python cat.py tables.csv
1,2,3,4,5
2,4,6,8,10
3,6,9,12,15
4,8,12,16,20
5,10,15,20,25
6,12,18,24,30
7,14,21,28,35
8,16,24,32,40
9,18,27,36,45
10,20,30,40,50
In [108]:
tsvwriter(tables, "tables.tsv")
In [109]:
!python cat.py tables.tsv
1	2	3	4	5
2	4	6	8	10
3	6	9	12	15
4	8	12	16	20
5	10	15	20	25
6	12	18	24	30
7	14	21	28	35
8	16	24	32	40
9	18	27	36	45
10	20	30	40	50

Writing to standard error and standard output

In [111]:
import sys
In [112]:
sys.stderr.write("Error: Something went wrong")
Error: Something went wrong
In [113]:
sys.stdout.write("This is just for information..")
This is just for information..

Working with dictionaries

In [115]:
author = {"name":"Lewis Carrol",
         "books":["Alice in wonderland", "Looking through the glass"],
         "language":"english"}
In [116]:
author
Out[116]:
{'books': ['Alice in wonderland', 'Looking through the glass'],
 'language': 'english',
 'name': 'Lewis Carrol'}
In [117]:
author["name"]
Out[117]:
'Lewis Carrol'
In [118]:
author["books"]
Out[118]:
['Alice in wonderland', 'Looking through the glass']
In [119]:
author["country"] = "UK"
In [120]:
author
Out[120]:
{'books': ['Alice in wonderland', 'Looking through the glass'],
 'country': 'UK',
 'language': 'english',
 'name': 'Lewis Carrol'}
In [121]:
del author['country']
In [122]:
author
Out[122]:
{'books': ['Alice in wonderland', 'Looking through the glass'],
 'language': 'english',
 'name': 'Lewis Carrol'}
In [123]:
d = {True:1, False:0}
In [124]:
d
Out[124]:
{False: 0, True: 1}
In [125]:
[[d[i==j] for i in range(5)] for j in range(5)]
Out[125]:
[[1, 0, 0, 0, 0],
 [0, 1, 0, 0, 0],
 [0, 0, 1, 0, 0],
 [0, 0, 0, 1, 0],
 [0, 0, 0, 0, 1]]
In [126]:
author['country']
---------------------------------------------------------------------------
KeyError                                  Traceback (most recent call last)
<ipython-input-126-e6bf6cefc7cc> in <module>()
----> 1 author['country']

KeyError: 'country'
In [127]:
author.get("country", "UK")
Out[127]:
'UK'
In [128]:
author
Out[128]:
{'books': ['Alice in wonderland', 'Looking through the glass'],
 'language': 'english',
 'name': 'Lewis Carrol'}
In [129]:
del author['books']
In [130]:
author
Out[130]:
{'language': 'english', 'name': 'Lewis Carrol'}
In [131]:
author.get("books", [])
Out[131]:
[]
In [132]:
"name" in author
Out[132]:
True
In [133]:
"books" in author
Out[133]:
False
In [134]:
"language" in author
Out[134]:
True
In [135]:
"english" in author
Out[135]:
False
In [136]:
author
Out[136]:
{'language': 'english', 'name': 'Lewis Carrol'}
In [137]:
"english" in author.values()
Out[137]:
True
In [138]:
author.values()
Out[138]:
dict_values(['Lewis Carrol', 'english'])
In [139]:
author.keys()
Out[139]:
dict_keys(['name', 'language'])
In [140]:
author.items()
Out[140]:
dict_items([('name', 'Lewis Carrol'), ('language', 'english')])

my grub conf looks like this ...

In [150]:
%%file grub.cnf
# /boot/grub/grub.cfg.
# For full documentation of the options in this file, see:
#   info -f grub -n 'Simple configuration'

GRUB_DEFAULT=0
GRUB_HIDDEN_TIMEOUT=0
GRUB_HIDDEN_TIMEOUT_QUIET=true
GRUB_TIMEOUT=10
GRUB_DISTRIBUTOR=`lsb_release -i -s 2> /dev/null || echo Debian`
GRUB_CMDLINE_LINUX_DEFAULT="quiet splash modlbs=off wifi=off"
GRUB_CMDLINE_LINUX=""

# Uncomment to enable BadRAM filtering, modify to suit your needs
# This works with Linux (no patch required) and with any kernel that obtains
# the memory map information from GRUB (GNU Mach, kernel of FreeBSD ...)
#GRUB_BADRAM="0x01234567,0xfefefefe,0x89abcdef,0xefefefef"

# Uncomment to disable graphical terminal (grub-pc only)
#GRUB_TERMINAL=console

# The resolution used on graphical terminal
# note that you can use only modes which your graphic card supports via VBE
# you can see them in real GRUB with the command `vbeinfo'
#GRUB_GFXMODE=640x480

# Uncomment if you don't want GRUB to pass "root=UUID=xxx" parameter to Linux
#GRUB_DISABLE_LINUX_UUID=true

# Uncomment to disable generation of recovery mode menu entries
#GRUB_DISABLE_RECOVERY="true"

# Uncomment to get a beep at grub start
#GRUB_INIT_TUNE="480 440 1"
Writing grub.cnf
In [158]:
def parsegrubconf(conffile):
    grubconf = {}
    with open(conffile) as conf:
        for line in conf:
            if line.startswith("#") or line.strip()=="":
                continue
            else:
                tokens = line.strip().split("=")
                grubconf[tokens[0]] = "=".join(tokens[1:])
    return grubconf
In [159]:
conf = parsegrubconf("grub.cnf")
In [152]:
conf['GRUB_CMDLINE_LINUX']
Out[152]:
'""'
In [153]:
conf['GRUB_TIMEOUT']
Out[153]:
'10'
In [161]:
conf
Out[161]:
{'GRUB_CMDLINE_LINUX': '""',
 'GRUB_CMDLINE_LINUX_DEFAULT': '"quiet splash modlbs=off wifi=off"',
 'GRUB_DEFAULT': '0',
 'GRUB_DISTRIBUTOR': '`lsb_release -i -s 2> /dev/null || echo Debian`',
 'GRUB_HIDDEN_TIMEOUT': '0',
 'GRUB_HIDDEN_TIMEOUT_QUIET': 'true',
 'GRUB_TIMEOUT': '10'}
In [164]:
s = "hello world few more words"
In [165]:
help(s.split)
Help on built-in function split:

split(...) method of builtins.str instance
    S.split(sep=None, maxsplit=-1) -> list of strings
    
    Return a list of the words in S, using sep as the
    delimiter string.  If maxsplit is given, at most maxsplit
    splits are done. If sep is not specified or is None, any
    whitespace string is a separator and empty strings are
    removed from the result.

In [166]:
s.split(maxsplit=1)
Out[166]:
['hello', 'world few more words']

Word frequency example

In [167]:
%%file words.txt
one
one two
one two three
one two three four
one two three four five
one two three five six
one two five six seven
one five six 
five six
five
Writing words.txt
In [175]:
%%file wordfreq.py
import sys

def getwords(file):
    return open(file).read().split()

def wordfreq(words):
    freq = {}
    for word in words:
        if word in freq:
            freq[word] += 1
        else:
            freq[word] = 1
    return freq

def wordfreq1(words):
    freq = {}
    for word in words:
        freq[word] = freq.get(word, 0) + 1
    return freq

def wordfreq2(words):
    uniq = set(words)
    freq = {}
    for w in uniq:
        freq[w] = words.count(w)
    return freq

if __name__ == "__main__":
    words = getwords(sys.argv[1])
    print(wordfreq(words))
Overwriting wordfreq.py
In [174]:
!python wordfreq.py words.txt
{'one': 8, 'two': 6, 'three': 4, 'four': 2, 'five': 6, 'six': 4, 'seven': 1}
In [200]:
set([1,1,1,2,3,2,3,4]) # set is unique collection of objects
Out[200]:
{1, 2, 3, 4}
In [177]:
import wordfreq
In [178]:
words = wordfreq.getwords("words.txt")
In [179]:
wordfreq.wordfreq(words)
Out[179]:
{'five': 6, 'four': 2, 'one': 8, 'seven': 1, 'six': 4, 'three': 4, 'two': 6}
In [180]:
wordfreq.wordfreq1(words)
Out[180]:
{'five': 6, 'four': 2, 'one': 8, 'seven': 1, 'six': 4, 'three': 4, 'two': 6}
In [181]:
wordfreq.wordfreq2(words)
Out[181]:
{'five': 6, 'four': 2, 'one': 8, 'seven': 1, 'six': 4, 'three': 4, 'two': 6}

Iterating over dictionaries

In [182]:
freq = wordfreq.wordfreq(words) 
In [183]:
for key in freq:
    print(key, freq[key])
one 8
two 6
three 4
four 2
five 6
six 4
seven 1
In [184]:
for key in freq.keys():
    print(key, freq[key])
one 8
two 6
three 4
four 2
five 6
six 4
seven 1
In [186]:
for value in freq.values():
    print(value)
8
6
4
2
6
4
1
In [187]:
for key, value in freq.items():
    print(key, value)
one 8
two 6
three 4
four 2
five 6
six 4
seven 1
In [188]:
for key, value in sorted(freq.items()):
    print(key, value)
five 6
four 2
one 8
seven 1
six 4
three 4
two 6
In [189]:
def getvalue(pair):
    return pair[1]

for key, value in sorted(freq.items(), key=getvalue):
    print(key, value)
seven 1
four 2
three 4
six 4
two 6
five 6
one 8
In [190]:
for key, value in sorted(freq.items(), key=getvalue, reverse=True):
    print(key, value)
one 8
two 6
five 6
three 4
six 4
four 2
seven 1
In [202]:
for key, value in sorted(freq.items(), key=getvalue, reverse=True):
    print(key.rjust(5), value)
  one 8
  two 6
 five 6
three 4
  six 4
 four 2
seven 1
In [204]:
for key, value in sorted(freq.items(), key=getvalue, reverse=True):
    print(key.rjust(5), value, "*"*value)
  one 8 ********
  two 6 ******
 five 6 ******
three 4 ****
  six 4 ****
 four 2 **
seven 1 *
In [194]:
names = ["Anand","Naufal", "Vikrant", "David", "Alice", "Isac"]
countires = ["India", "India", "India", "USA", "UK", "USA"]
In [195]:
dict(zip(names, countires))
Out[195]:
{'Alice': 'UK',
 'Anand': 'India',
 'David': 'USA',
 'Isac': 'USA',
 'Naufal': 'India',
 'Vikrant': 'India'}
In [197]:
d = {[]:"empty",
    [1,1,1]:"ones"}
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-197-8d7dfeb2ed78> in <module>()
      1 d = {[]:"empty",
----> 2     [1,1,1]:"ones"}

TypeError: unhashable type: 'list'
In [198]:
d = {(1,):1,
    (1,2):2}
In [199]:
d
Out[199]:
{(1,): 1, (1, 2): 2}

Why classes?

Lets try to model bank account

In [205]:
%%file bank0.py

balance = 0

def get_balance():
    return balance

def deposite(amount):
    global balance
    balance += amount
    
def withdraw(amount):
    global balance
    balance -= amount
    
if __name__ == "__main__":
    deposite(100)
    print(get_balance())
    withdraw(20)
    print(get_balance())
    
Writing bank0.py
In [206]:
%%file m.py

a = 2
b = 3
def func():
    return a+b
Writing m.py
In [207]:
import m
In [208]:
m.a
Out[208]:
2
In [209]:
m.b
Out[209]:
3
In [210]:
m.func()
Out[210]:
5
In [213]:
%%file bank1.py

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

def get_balance(account):
    return account['balance']

def deposite(account, amount):
    account['balance'] += amount
    
def withdraw(account, amount):
    account['balance'] -= amount
    

if __name__ == "__main__":
    a1 = create_account()
    a2 = create_account()
    deposite(a1, 100)
    deposite(a2, 200)
    print("a1 ", get_balance(a1))
    print("a2 ", get_balance(a2))
    withdraw(a1, 10)
    withdraw(a2, 20)
    print("a1 ", get_balance(a1))
    print("a2 ", get_balance(a2))
Overwriting bank1.py
In [214]:
!python bank1.py 
a1  100
a2  200
a1  90
a2  180
In [217]:
%%file bank2.py

class BankAccount:
    
    def __init__(self):
        self.balance = 0
        
    def get_balance(self):
        return self.balance
    
    def deposit(self, amount):
        self.balance += amount
        
    def withdraw(self, amount):
        self.balance -= amount

if __name__ == "__main__":
    a1 = BankAccount()
    a2 = BankAccount()
    a1.deposit(100)
    a2.deposit(200)
    print("a1 ", a1.get_balance())
    print("a2 ", a2.get_balance())
    a1.withdraw(20)
    a2.withdraw(30)
    print("a1 ", a1.get_balance())
    print("a2 ", a2.get_balance())
    
Overwriting bank2.py
In [218]:
!python bank2.py
a1  100
a2  200
a1  80
a2  170
In [219]:
class Foo:
    pass
In [220]:
class Point:
    def __init__(self, x, y):
        self.x = x
        self.y = y
In [222]:
class Point:
    def __init__(obj, x, y): # this will also work, but by convention we use self
        obj.x = x
        obj.y = y
In [223]:
p = Point(1,2)
In [224]:
type(p)
Out[224]:
__main__.Point
In [225]:
def f():
    pass
In [226]:
f
Out[226]:
<function __main__.f>
In [227]:
class Foo:
    pass
In [228]:
Foo
Out[228]:
__main__.Foo
In [229]:
p.x
Out[229]:
1
In [230]:
p.y
Out[230]:
2
In [231]:
p.z = 3
In [232]:
p.z
Out[232]:
3
In [233]:
p.x = -1
In [234]:
p.x
Out[234]:
-1
In [235]:
p.__dict__
Out[235]:
{'x': -1, 'y': 2, 'z': 3}

problem

  • Write a class Timer, which can be used to time tasks. it should work as given below. hint:time.time()
t = Timer()
t.start()
do some work
t.stop()
print(t.get_time_taken())
In [236]:
import time
In [237]:
time.time()
Out[237]:
1516353620.048532
In [238]:
import time
class Timer:
    def __init__(self):
        self._start = 0
        self._end = 0
        
    def start(self):
        self._start = time.time()
        
    def stop(self):
        self._end = time.time()
        
    def get_time_taken(self):
        return self._end - self._start
    
    def reset(self):
        self._start = 0
        self._end = 0
        
In [239]:
t = Timer()
t.start()
In [240]:
time.sleep(2)
In [241]:
t.stop()
In [242]:
print(t.get_time_taken())
16.38936138153076
In [243]:
t.start()
In [244]:
t.get_time_taken()
Out[244]:
-88.4480152130127
In [245]:
t.reset()

Exceptions

In [246]:
names = ["Anand","Naufal", "Vikrant", "David", "Alice", "Isac"]
countires = ["India", "India", "India", "USA", "UK", "USA"]
In [247]:
dict([(1,"one"), (2,"two")])
Out[247]:
{1: 'one', 2: 'two'}
In [248]:
teams = dict(zip(names, countires))
In [249]:
teams
Out[249]:
{'Alice': 'UK',
 'Anand': 'India',
 'David': 'USA',
 'Isac': 'USA',
 'Naufal': 'India',
 'Vikrant': 'India'}
In [250]:
teams['Asimov']
---------------------------------------------------------------------------
KeyError                                  Traceback (most recent call last)
<ipython-input-250-d1fbe5f006c0> in <module>()
----> 1 teams['Asimov']

KeyError: 'Asimov'
In [251]:
doom
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
<ipython-input-251-301636d58674> in <module>()
----> 1 doom

NameError: name 'doom' is not defined
In [252]:
2 + "3"
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-252-2068cae7beb7> in <module>()
----> 1 2 + "3"

TypeError: unsupported operand type(s) for +: 'int' and 'str'
In [253]:
open("sdkjhfkdsjhfkjds")
---------------------------------------------------------------------------
FileNotFoundError                         Traceback (most recent call last)
<ipython-input-253-27e91b799f33> in <module>()
----> 1 open("sdkjhfkdsjhfkjds")

FileNotFoundError: [Errno 2] No such file or directory: 'sdkjhfkdsjhfkjds'
In [254]:
def parseint(strvalue):
    return int(strvalue)
In [255]:
parseint("42")
Out[255]:
42
In [256]:
parseint("Nan")
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-256-e5485772f304> in <module>()
----> 1 parseint("Nan")

<ipython-input-254-9845c4807f9e> in parseint(strvalue)
      1 def parseint(strvalue):
----> 2     return int(strvalue)

ValueError: invalid literal for int() with base 10: 'Nan'
In [258]:
def parseint(strvalue):
    try:
        return int(strvalue)
    except ValueError as e:
        print("Handled :", e)
        return 0
    
In [259]:
parseint("Nan")
Handled : invalid literal for int() with base 10: 'Nan'
Out[259]:
0
In [262]:
def csvparser(file):
    return [[int(item) for item in line.strip().split(",")] for line in open(file)]
In [263]:
def csvparser_missing(file):
    return [[parseint(item) for item in line.strip().split(",")] for line in open(file)]
In [264]:
%%file nums.csv
1,2,3
4,,5
6,7,Nan
Writing nums.csv
In [265]:
csvparser("nums.csv")
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-265-7136d0e78922> in <module>()
----> 1 csvparser("nums.csv")

<ipython-input-262-c5d85f9b2362> in csvparser(file)
      1 def csvparser(file):
----> 2     return [[int(item) for item in line.strip().split(",")] for line in open(file)]

<ipython-input-262-c5d85f9b2362> in <listcomp>(.0)
      1 def csvparser(file):
----> 2     return [[int(item) for item in line.strip().split(",")] for line in open(file)]

<ipython-input-262-c5d85f9b2362> in <listcomp>(.0)
      1 def csvparser(file):
----> 2     return [[int(item) for item in line.strip().split(",")] for line in open(file)]

ValueError: invalid literal for int() with base 10: ''
In [266]:
csvparser_missing("nums.csv")
Handled : invalid literal for int() with base 10: ''
Handled : invalid literal for int() with base 10: 'Nan'
Out[266]:
[[1, 2, 3], [4, 0, 5], [6, 7, 0]]

Building commandline applications

In [283]:
%%file head.py
"""
head module implements unix command head approximately
"""
import argparse

def head(file, n):
    filehandle = open(file)
    line = filehandle.readline()
    count = 1
    while line and count<=n:
        print(line, end="")
        count += 1
        line = filehandle.readline()
        
        
def parse_args():
    parser = argparse.ArgumentParser()
    parser.add_argument("file", type=str,
                       help="File in which to look for")
    parser.add_argument("-n", "--lines", 
                        type=int,
                        help="Number of lines to be seen as head")
    return parser.parse_args()
    
if __name__ == "__main__":
    args = parse_args()
    if args.lines:
        head(args.file, args.lines)
    else:
        head(args.file, 5)
        
Overwriting head.py
In [284]:
!python head.py data.txt
The Zen of Python, by Tim Peters

Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
In [297]:
%%file args.py
"""
head module implements unix command head approximately
"""
import argparse


def parse_args():
    parser = argparse.ArgumentParser()
    parser.add_argument("files",type=str,
                        nargs="+",
                       help="Files in which to look for")
    parser.add_argument("-n", "--lines", 
                        type=int,
                        help="Number of lines to be seen as head")
    parser.add_argument("-f", 
                       help="optional flag",
                       action="store_true")
    return parser.parse_args()
    
if __name__ == "__main__":
    args = parse_args()
    print(args)
    
Overwriting args.py
In [298]:
!python args.py -n 5 data.txt jkjsdhdf jksddj
Namespace(f=False, files=['data.txt', 'jkjsdhdf', 'jksddj'], lines=5)

problem

  • improve the script cat.py to have positional arguments and additional option "-n" which if given cat.py prints line numbers at start of line.

regular expressions

In [299]:
import re
In [300]:
pattern = re.compile("^def\s+[a-zA-Z]+\(.*\):")
In [303]:
m = pattern.match("def hello():")
In [304]:
m
Out[304]:
<_sre.SRE_Match object; span=(0, 12), match='def hello():'>
In [305]:
pattern = re.compile("^def\s+([a-zA-Z]+)\(.*\):")
In [306]:
m = pattern.match("def hello():")
In [307]:
m
Out[307]:
<_sre.SRE_Match object; span=(0, 12), match='def hello():'>
In [308]:
m.groups()
Out[308]:
('hello',)
In [319]:
def functions(pyfiles):
    funcp = re.compile("^def\s+([a-zA-Z]+)\(.*\):")
    funcs = []
    for file in pyfiles:
        for line in open(file):
            m = funcp.match(line)
            if m:
                funcs.append(m.groups()[0])
    return funcs
In [320]:
import os
In [321]:
pyfiles = [file for file in os.listdir(os.getcwd()) if file.endswith(".py")]
functions(pyfiles)
Out[321]:
['head',
 'getwords',
 'wordfreq',
 'deposite',
 'withdraw',
 'add',
 'square',
 'mult',
 'func',
 'addstrint',
 'cat',
 'catfiles',
 'listfiles',
 'deposite',
 'withdraw']
In [325]:
text = "some junk lkdljsfl 1hell3 kjfklfgj-090943unlkjrkltgj90485"
text2 = "kjsdhhfkjds kjhdsfkhsdkjh 987jhkfdskjh 1ghfh9 lkdfjlkds90m.?;ljfsdh"
p = re.compile("(.*)([0-9]{1,1}[a-z]{4,4}[0-9]{1,1})(.*)")
m1 = p.match(text)
m2 = p.match(text2)
In [326]:
m1
Out[326]:
<_sre.SRE_Match object; span=(0, 57), match='some junk lkdljsfl 1hell3 kjfklfgj-090943unlkjrkl>
In [327]:
m2
Out[327]:
<_sre.SRE_Match object; span=(0, 67), match='kjsdhhfkjds kjhdsfkhsdkjh 987jhkfdskjh 1ghfh9 lkd>
In [328]:
m1.groups()
Out[328]:
('some junk lkdljsfl ', '1hell3', ' kjfklfgj-090943unlkjrkltgj90485')
In [329]:
m2.groups()
Out[329]:
('kjsdhhfkjds kjhdsfkhsdkjh 987jhkfdskjh ', '1ghfh9', ' lkdfjlkds90m.?;ljfsdh')

Downloading stuff from internet

In [330]:
import requests
In [336]:
response = requests.get("http://httpbin.org/html")
print(response.text[:400])
<html>
<head>
<meta http-equiv='refresh' content='1; url=http://httpbin.org/html&arubalp=e92a1063-4b38-4bd0-bab1-476d4c3d8e'>
</head>
</html>

In [337]:
response.headers
Out[337]:
{'Date': 'Fri, 19 Jan 2018 11:21:56 GMT', 'Server': 'Apache', 'X-Frame-Options': 'SAMEORIGIN', 'X-UA-Compatible': 'IE=edge;IE=11;IE=10;IE=9', 'Expires': '0', 'Content-Length': '142', 'Connection': 'close', 'Content-Type': 'text/html'}
In [343]:
response = requests.get("http://httpbin.org/get", params={"parameters":"dummy", "language":"python"})
In [342]:
print(response.text)
<html>
<head>
<meta http-equiv='refresh' content='1; url=http://httpbin.org/get?parameters=dummy&amp;language=python&arubalp=e92a1063-4b38-4bd0-bab1-476d4c3d8e'>
</head>
</html>

In [344]:
response = requests.post("http://httpbin.org/post", data={"name":"alice","email":"asa@kj.com"})
In [349]:
print(response.text[:100])
<!doctype html>
<html lang="en">
<head>
	<meta http-equiv="Content-Type" content="text/html; charset
In [354]:
import requests
url = "https://api.github.com/orgs/vmware/repos"
repos = requests.get(url).json()
In [355]:
type(repos)
Out[355]:
list
In [356]:
for repo in repos:
    print(repo['full_name'], repo['forks'])
vmware/pyvco 4
vmware/rvc 46
vmware/rbvmomi 153
vmware/vprobe-toolkit 9
vmware/CloudFS 16
vmware/vcd-nclient 2
vmware/lmock 5
vmware/FireBreath 2
vmware/weasel 1
vmware/vmware-vcenter 86
vmware/vmware-vshield 6
vmware/vcloud-rest 37
vmware/GemstoneWebTools 0
vmware/vmware-vcsa 17
vmware/vmware-vmware_lib 24
vmware/saml20serviceprovider 1
vmware/pg_rewind 18
vmware/vco-powershel-plugin 2
vmware/jenkins-reviewbot 12
vmware/dbeekeeper 0
vmware/thinapp_factory 16
vmware/vmware-cassandra 4
vmware/vmware-java 0
vmware/data-driven-framework 3
vmware/pyvmomi 463
vmware/pyvmomi-community-samples 393
vmware/open-vm-tools 154
vmware/pyvmomi-tools 17
vmware/upgrade-framework 11
vmware/webcommander 32
In [359]:
for repo in sorted(repos, key=lambda rep:rep["forks"], reverse=True)[:5]:
    print(repo['full_name'], repo['forks'])
vmware/pyvmomi 463
vmware/pyvmomi-community-samples 393
vmware/open-vm-tools 154
vmware/rbvmomi 153
vmware/vmware-vcenter 86

problem

  • Find distance between two cities using google api
    url="https://maps.googleapis.com/maps/api/distancematrix/json"
    paramaeter reqauired :
    origins
    destinations
    units (metric)
In [364]:
def distance(source, dest):
    url = "https://maps.googleapis.com/maps/api/distancematrix/json"
    r = requests.get(url, params={"origins":source,
                                  "destinations":dest,
                                  "units":"metric"})
    #return r.json()
    return r.json()['rows'][0]['elements'][0]['distance']['text']
In [361]:
data = distance("bangalore", "mumbai")
In [362]:
data
Out[362]:
{'destination_addresses': ['Mumbai, Maharashtra, India'],
 'origin_addresses': ['Bengaluru, Karnataka, India'],
 'rows': [{'elements': [{'distance': {'text': '980 km', 'value': 980127},
     'duration': {'text': '14 hours 49 mins', 'value': 53317},
     'status': 'OK'}]}],
 'status': 'OK'}
In [363]:
data['rows'][0]['elements'][0]['distance']['text']
Out[363]:
'980 km'
In [365]:
distance("chennai", "bangalore")
Out[365]:
'347 km'

References and practice material

Practice book

Euler

python docs

SICP

google for bangpypers

Suggested mini projects.

  • tetsing
  • backup
  • tr
  • directorytree
In [ ]: