Advanced Python Training at VMWare - Day 1

May 28-30, 2018 Vikrant Patil

These notes are available online at http://notes.pipal.in/2018/vmware-advanced-may

© Pipal Academy LLP

Day 1 | Day 2 | Day 3

Python distribution

We will be using jupyter which comes with anaconda (python 3) distribution for this training. it can be downloaded from

https://www.anaconda.com/download/

In [1]:
2 + 3
Out[1]:
5

Header

bold

strigs , lists, dictionary, tuple

In [2]:
name = "first" "second"
In [3]:
name
Out[3]:
'firstsecond'
In [4]:
"first" in name
Out[4]:
True
In [5]:
if "first" in name:
    print("yes it is!")
yes it is!
In [6]:
"first" + "second"
Out[6]:
'firstsecond'
In [7]:
a = "first"
b = "second"
In [8]:
c = a b
  File "<ipython-input-8-7a20e25ce503>", line 1
    c = a b
          ^
SyntaxError: invalid syntax
In [9]:
book = "Alice in wonderland"
In [10]:
book.split(" ")
Out[10]:
['Alice', 'in', 'wonderland']
In [11]:
book.split()
Out[11]:
['Alice', 'in', 'wonderland']
In [12]:
"Alice     in \t wonderland".split()
Out[12]:
['Alice', 'in', 'wonderland']
In [13]:
s = "BOOT_LOADER=/boot/...."
In [14]:
s.split("=")
Out[14]:
['BOOT_LOADER', '/boot/....']
In [15]:
s = "options= 'wifi=off blootoon=on'"
In [16]:
s.split("=")
Out[16]:
['options', " 'wifi", 'off blootoon', "on'"]
In [17]:
s.split(maxsplit=1)
Out[17]:
['options=', "'wifi=off blootoon=on'"]
In [18]:
s.split("=", maxsplit=1)
Out[18]:
['options', " 'wifi=off blootoon=on'"]
In [19]:
import os
In [20]:
os.path.sep
Out[20]:
'/'
In [22]:
path = ["","home","vikrant","training","2018","vmware-advanced-may"]
In [24]:
curretdir = os.path.sep.join(path)
In [25]:
curretdir
Out[25]:
'/home/vikrant/training/2018/vmware-advanced-may'
In [26]:
"  hello python    \n".strip()
Out[26]:
'hello python'

lists

In [27]:
l = [1,"a",[1,2,3],4]
In [28]:
l[0]
Out[28]:
1
In [29]:
len(l)
Out[29]:
4
In [30]:
l[-1]
Out[30]:
4
In [31]:
numbers = list(range(0,10,1))
In [32]:
numbers
Out[32]:
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
In [34]:
numbers[1:4] # start at index 1, stop at index 4 (excluding)
Out[34]:
[1, 2, 3]
In [35]:
numbers[1:7:2] # start at index 1, stop at index 7 (excluding) at interval of 2
Out[35]:
[1, 3, 5]
In [36]:
numbers[:3]
Out[36]:
[0, 1, 2]
In [37]:
numbers[2:]
Out[37]:
[2, 3, 4, 5, 6, 7, 8, 9]
In [38]:
numbers[::-1]
Out[38]:
[9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
In [39]:
def is_palindrome(w):
    return w == w[::-1]
In [40]:
is_palindrome("madam")
Out[40]:
True
In [42]:
for n in numbers:
    print(n*n, end=",")
0,1,4,9,16,25,36,49,64,81,
In [43]:
squares = [n*n for n in numbers]
In [44]:
squares
Out[44]:
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
In [45]:
cubes = [n**3 for n in numbers]
In [46]:
cubes
Out[46]:
[0, 1, 8, 27, 64, 125, 216, 343, 512, 729]
In [47]:
[[i*j for j in range(1,11)] for i in range(1,6)]
Out[47]:
[[1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
 [2, 4, 6, 8, 10, 12, 14, 16, 18, 20],
 [3, 6, 9, 12, 15, 18, 21, 24, 27, 30],
 [4, 8, 12, 16, 20, 24, 28, 32, 36, 40],
 [5, 10, 15, 20, 25, 30, 35, 40, 45, 50]]
In [48]:
t = [[i*j for j in range(1,11)] for i in range(1,6)]
In [49]:
t[0]
Out[49]:
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
In [50]:
t[1]
Out[50]:
[2, 4, 6, 8, 10, 12, 14, 16, 18, 20]
In [52]:
t[0] # 0th row
Out[52]:
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
In [53]:
t[0][0]
Out[53]:
1
In [54]:
len(t)
Out[54]:
5
In [55]:
def column(data, n):
    return [data[r][n] for r in range(len(data))]
In [56]:
column(t, 0)
Out[56]:
[1, 2, 3, 4, 5]
In [57]:
column(t, 2)
Out[57]:
[3, 6, 9, 12, 15]
In [58]:
def transpose(data):
    numcols = len(data[0])
    return [column(data, i) for i in range(numcols)]
In [59]:
transpose(t)
Out[59]:
[[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]]

dictionary

In [61]:
person = {"name":"Alice", "age":9, "email":"alice@wonder.land"}
In [62]:
person["name"]
Out[62]:
'Alice'
In [63]:
person["age"]
Out[63]:
9
In [64]:
person["hello"]
---------------------------------------------------------------------------
KeyError                                  Traceback (most recent call last)
<ipython-input-64-9859c9b28300> in <module>()
----> 1 person["hello"]

KeyError: 'hello'
In [65]:
if "name" in person:
    print(person["name"])
Alice
In [66]:
person.get("country", "India")
Out[66]:
'India'
In [67]:
person
Out[67]:
{'age': 9, 'email': 'alice@wonder.land', 'name': 'Alice'}
In [68]:
for key in person:
    print(key)
name
age
email
In [69]:
for key, value in person.items():
    print(key, value)
name Alice
age 9
email alice@wonder.land
In [70]:
d = {[1,2,3]:"list"}
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-70-bfbfd694d874> in <module>()
----> 1 d = {[1,2,3]:"list"}

TypeError: unhashable type: 'list'
In [71]:
d  = {"list":[1,2,32,4]}
In [72]:
d
Out[72]:
{'list': [1, 2, 32, 4]}
In [73]:
d = {(1,2,3):"tuple"}

You can put only hashable items as a key in dictionary

files

In [74]:
with open("numbers.txt","w") as f:
    f.write("one\n")
    f.write("two\n")
    f.write("three\n")
    
In [75]:
for line in open("numbers.txt"):
    print(line, end="")
one
two
three

problem

  • Write a function csvparse which will parse a csv file and return 2d list of data in the file
In [76]:
t
Out[76]:
[[1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
 [2, 4, 6, 8, 10, 12, 14, 16, 18, 20],
 [3, 6, 9, 12, 15, 18, 21, 24, 27, 30],
 [4, 8, 12, 16, 20, 24, 28, 32, 36, 40],
 [5, 10, 15, 20, 25, 30, 35, 40, 45, 50]]
In [78]:
with open("tables.csv", "w") as f:
    for row in t:
        line  = ",".join([str(n) for n in row])
        f.write(line)
        f.write("\n")
    
In [79]:
!cat tables.csv
1,2,3,4,5,6,7,8,9,10
2,4,6,8,10,12,14,16,18,20
3,6,9,12,15,18,21,24,27,30
4,8,12,16,20,24,28,32,36,40
5,10,15,20,25,30,35,40,45,50
In [80]:
def cat(file):
    for line in open(file):
        print(line, end="")
In [81]:
cat("tables.csv")
1,2,3,4,5,6,7,8,9,10
2,4,6,8,10,12,14,16,18,20
3,6,9,12,15,18,21,24,27,30
4,8,12,16,20,24,28,32,36,40
5,10,15,20,25,30,35,40,45,50
In [86]:
def csvpaser1(file):
    return [line for line in open(file)]
In [83]:
csvpaser1("tables.csv")
Out[83]:
['1,2,3,4,5,6,7,8,9,10\n',
 '2,4,6,8,10,12,14,16,18,20\n',
 '3,6,9,12,15,18,21,24,27,30\n',
 '4,8,12,16,20,24,28,32,36,40\n',
 '5,10,15,20,25,30,35,40,45,50\n']
In [88]:
def csvpaser2(file):
    return [line.strip().split(",") for line in open(file)]
In [89]:
csvpaser2("tables.csv")
Out[89]:
[['1', '2', '3', '4', '5', '6', '7', '8', '9', '10'],
 ['2', '4', '6', '8', '10', '12', '14', '16', '18', '20'],
 ['3', '6', '9', '12', '15', '18', '21', '24', '27', '30'],
 ['4', '8', '12', '16', '20', '24', '28', '32', '36', '40'],
 ['5', '10', '15', '20', '25', '30', '35', '40', '45', '50']]
In [90]:
def csvpaser(file):
    return [[int(i) for i in line.strip().split(",")] for line in open(file)]
In [91]:
csvpaser("tables.csv")
Out[91]:
[[1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
 [2, 4, 6, 8, 10, 12, 14, 16, 18, 20],
 [3, 6, 9, 12, 15, 18, 21, 24, 27, 30],
 [4, 8, 12, 16, 20, 24, 28, 32, 36, 40],
 [5, 10, 15, 20, 25, 30, 35, 40, 45, 50]]
In [92]:
def csvpaser(file):
    with open(file) as f:
        d = [[int(i) for i in line.strip().split(",")] for line in f]
    return d
In [93]:
csvpaser("tables.csv")
Out[93]:
[[1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
 [2, 4, 6, 8, 10, 12, 14, 16, 18, 20],
 [3, 6, 9, 12, 15, 18, 21, 24, 27, 30],
 [4, 8, 12, 16, 20, 24, 28, 32, 36, 40],
 [5, 10, 15, 20, 25, 30, 35, 40, 45, 50]]

Functions

In [94]:
def twice(x) :
    return 2*x

def twice1(x):
    print(2*x)
In [95]:
twice(3)
Out[95]:
6
In [96]:
twice1(3)
6
In [97]:
x = twice(4)
y = twice1(4)
8
In [98]:
x
Out[98]:
8
In [99]:
y
In [100]:
twice(twice(2))
Out[100]:
8
In [101]:
twice1(twice1(3))
6
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-101-c3f6229d2002> in <module>()
----> 1 twice1(twice1(3))

<ipython-input-94-288241ec99c4> in twice1(x)
      3 
      4 def twice1(x):
----> 5     print(2*x)

TypeError: unsupported operand type(s) for *: 'int' and 'NoneType'

Positional arguments

In [102]:
import math
def cyl_volume(radius, height):
    return math.pi*radius**2*height
In [103]:
cyl_volume(1.0, 2.0)
Out[103]:
6.283185307179586
In [104]:
cyl_volume(2.0, 1.0)
Out[104]:
12.566370614359172
In [105]:
cyl_volume(radius=1.0, height=2.0)
Out[105]:
6.283185307179586
In [106]:
cyl_volume(1.0, height=2.0)
Out[106]:
6.283185307179586
In [107]:
cyl_volume(radius=1.0, 2.0)
  File "<ipython-input-107-0d18dd1ab23e>", line 1
    cyl_volume(radius=1.0, 2.0)
                          ^
SyntaxError: positional argument follows keyword argument
In [108]:
cyl_volume(height=2.0, radius=1.0)
Out[108]:
6.283185307179586
In [109]:
def cyl_volume(radius=1.0, height=10):
    return math.pi*radius**2*height
In [110]:
cyl_volume()
Out[110]:
31.41592653589793
In [111]:
cyl_volume(height=2)
Out[111]:
6.283185307179586
In [112]:
cyl_volume(2)
Out[112]:
125.66370614359172
In [119]:
def append(value, data=[]):
    data.append(value)
    return data
In [125]:
l = ["A"]
In [126]:
l = append("B", l)
In [127]:
l 
Out[127]:
['A', 'B']
In [128]:
l2= append("A")

In [129]:
l2
Out[129]:
['A', 'A']
In [130]:
l2= append("A")
In [131]:
l2
Out[131]:
['A', 'A', 'A']
In [132]:
def append(value, data=None):
    if not data:
        data = []
    data.append(value)
    return data
In [133]:
t = (1,2,3,4)
In [134]:
t[0] = 3
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-134-d7bb3c58ee7f> in <module>()
----> 1 t[0] = 3

TypeError: 'tuple' object does not support item assignment
In [135]:
t = ([],2,3,4,5)
In [136]:
t[0]
Out[136]:
[]
In [137]:
t[0].append(1)
In [138]:
t
Out[138]:
([1], 2, 3, 4, 5)
In [139]:
t[0] = [1,3]
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-139-dabc79282f5f> in <module>()
----> 1 t[0] = [1,3]

TypeError: 'tuple' object does not support item assignment
In [140]:
type(t[0])
Out[140]:
list
In [141]:
(1,2,3,4,5)
Out[141]:
(1, 2, 3, 4, 5)

Named only argument

In [142]:
def cyl_volume(radius=1.0, *, height=10):
    return math.pi*radius**2*height
In [143]:
cyl_volume(2.0)
Out[143]:
125.66370614359172
In [144]:
cyl_volume(2.0, 20)
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-144-4d97c4bfc4d1> in <module>()
----> 1 cyl_volume(2.0, 20)

TypeError: cyl_volume() takes from 0 to 1 positional arguments but 2 were given
In [145]:
def cyl_volume(*, radius=1.0, height=10):
    return math.pi*radius**2*height
In [146]:
cyl_volume(1.0)
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-146-f1c5d95a0d36> in <module>()
----> 1 cyl_volume(1.0)

TypeError: cyl_volume() takes 0 positional arguments but 1 was given
In [147]:
cyl_volume(radius=1.0)
Out[147]:
31.41592653589793
In [148]:
cyl_volume(radius=1.0, height=10)
Out[148]:
31.41592653589793

Variable number of arguments

In [149]:
def mysum(*args):
    print(args)
In [150]:
mysum(1,2,3,4,5)
(1, 2, 3, 4, 5)
In [151]:
mysum(1,1,1)
(1, 1, 1)
In [152]:
def mysum(*args):
    s = 0
    for n in args:
        s += n
    return s
In [153]:
mysum(1,2,3,4)
Out[153]:
10

problem

  • Write a function myjoin which takes variable number of arguments and joins all given strings with first parameter.
    myjoin("_", "we","are","going", "functional","way")
    'we_are_going_functional_way'
In [154]:
items = (1,2,3,"3","A")
In [155]:
[str(item) for item in items]
Out[155]:
['1', '2', '3', '3', 'A']
In [156]:
def myjoin(joiner, *args):
    s = ""
    for item in args[:-1]:
        s += str(item) + joiner
    return s + args[-1]
    
In [158]:
myjoin("/","","home","vikrant","training")
Out[158]:
'/home/vikrant/training'

Unpacking arguments

In [159]:
mysum(1,2,3,4)
Out[159]:
10
In [169]:
def mean(*args):
    s = mysum(*args) # this is called as unpacking of arguments
    return s/len(args)
    
In [161]:
mean(1,2,3,4,5)
Out[161]:
3.0
In [166]:
def foo(*args):
    print(len(args))
    print(args)

def bar(*args):
    foo(args)
    
def bar1(*args):
    foo(*args)
In [167]:
bar(1,2,3,4,5,6)
1
((1, 2, 3, 4, 5, 6),)
In [168]:
bar1(1,2,3,4,5,6)
6
(1, 2, 3, 4, 5, 6)

Variable number of key value arguments

In [170]:
def make_person(**kwargs):
    d = {}
    for key, value in kwargs.items():
        d[key] = value
    return d
In [171]:
make_person(name="Alenzo Church", email="alenzo@lambda.in",language="lisp")
Out[171]:
{'email': 'alenzo@lambda.in', 'language': 'lisp', 'name': 'Alenzo Church'}
In [172]:
def fun(p1, p2, *args, **kwargs):
    pass

Functions Revisited

In [173]:
def square(x):
    return x*x
In [174]:
a = 2
In [175]:
a
Out[175]:
2
In [176]:
print(a)
2
In [177]:
type(a)
Out[177]:
int
In [178]:
square
Out[178]:
<function __main__.square>
In [179]:
type(square)
Out[179]:
function
In [180]:
x = a
In [181]:
print(x)
2
In [182]:
fun = square
In [183]:
square(2)
Out[183]:
4
In [ ]:
fun(3)
In [186]:
def sum_natural(start=1, end=100):
    s = 0
    for i in range(start, end+1):
        s += i
    return s

def sum_of_squares(start=1, end=100):
    s = 0
    for i in range(start, end+1):
        s += square(i)
        
    return s

def cube(x):
    return x*x*x
    
def sum_of_cubes(start=1, end=100):
    s = 0
    for i in range(start, end+1):
        s += cube(i)
        
    return s

def sum_(func, start, end):
    s  = 0
    for i in range(start, end+1):
        s += func(i)
    return s
In [187]:
sum_natural(1, 50)
Out[187]:
1275
In [188]:
def identity(x):
    return x 
In [189]:
sum_(identity, 1, 50)
Out[189]:
1275
In [190]:
sum_of_squares(1,50)
Out[190]:
42925
In [191]:
sum_(square, 1, 50)
Out[191]:
42925
In [192]:
sum_of_cubes(1,50)
Out[192]:
1625625
In [193]:
sum_(cube, 1, 50)
Out[193]:
1625625
In [194]:
max(["one", "two","three","four","five"])
Out[194]:
'two'
In [195]:
words = ["one", "two","three","four","five"]
In [196]:
max(words, key=len)
Out[196]:
'three'
In [197]:
records = [
    ("A", 9.0),
    ("B", 8.0),
    ("C", 5.0),
    ("D", 8.8),
    ("E", 8.7),
    ("F", 5.5)
]
In [199]:
max(records)
Out[199]:
('F', 5.5)
In [200]:
def get_score(r):
    return r[1]
In [201]:
max(records, key=get_score)
Out[201]:
('A', 9.0)
In [202]:
sorted(records)
Out[202]:
[('A', 9.0), ('B', 8.0), ('C', 5.0), ('D', 8.8), ('E', 8.7), ('F', 5.5)]
In [203]:
sorted(records, key=get_score)
Out[203]:
[('C', 5.0), ('F', 5.5), ('B', 8.0), ('E', 8.7), ('D', 8.8), ('A', 9.0)]
In [204]:
sorted(records, key=get_score, reverse=True)
Out[204]:
[('A', 9.0), ('D', 8.8), ('E', 8.7), ('B', 8.0), ('F', 5.5), ('C', 5.0)]
In [205]:
min(records, key=get_score)
Out[205]:
('C', 5.0)

8/3*5 + 8/7*9 + 8/11*13 ..... this converges to pi

In [212]:
def pi_func(n):
    return 8/((4*n-1)*(4*n+1))
In [214]:
sum_(pi_func, 1, 10000)*4
Out[214]:
3.4334293956404545

Functions as return value

In [215]:
def make_adder(x):
    
    def adder(y):
        return x+y
    
    return adder
In [216]:
aader5 = make_adder(5)
In [217]:
aader5
Out[217]:
<function __main__.make_adder.<locals>.adder>
In [218]:
aader5(4)
Out[218]:
9
In [219]:
aader5(11)
Out[219]:
16
In [220]:
adder4 = make_adder(4)
In [221]:
adder4(3)
Out[221]:
7
In [222]:
adder4(7)
Out[222]:
11
In [223]:
f = lambda x:x*x
In [224]:
f(3)
Out[224]:
9
In [225]:
m = lambda x,y: x*y
In [226]:
m(3,4)
Out[226]:
12
In [227]:
sum_(lambda x:x*x, 1, 50)
Out[227]:
42925
In [229]:
records = [
    ("A", 9.0, 90),
    ("B", 8.0, 110),
    ("C", 5.0, 115),
    ("D", 8.8, 120),
    ("E", 8.7, 95),
    ("F", 5.5, 107)
   ]
In [230]:
def column(i):
    return lambda r:r[i]
In [231]:
max(records, key=column(1))
Out[231]:
('A', 9.0, 90)
In [232]:
max(records, key=column(2))
Out[232]:
('D', 8.8, 120)

problem

  • Write a function repeat which takes a single argument function as first parameter and an integer, n as second parameter. it returns a new function which repeats original function n times.
    s3 = repeat(square, 3)
    s3(2) => square(square(square(2)))
  • Write a function make_logger which can create loggers of various level..for example warning, info, error...
warn = make_logger("[WARNING]:")
warn("Something might be wrong")
[WARNING]: Somthing might be wrong

info = make_logger("[INFO]:")
info("Just for information...process started all well")
[INFO]: Just for information...process started all well

Bonus problem

  • Write a function compose which takes two functions f anf g as parameters and returns a function which is composite of f and g as given below
fg = compose(f, g)
fg(x) => f(g(x))
In [241]:
square(square(square(square(square(11)))))
Out[241]:
2111377674535255285545615254209921
In [242]:
s = square(11)
for i in range(4):
    s = square(s)
In [243]:
s
Out[243]:
2111377674535255285545615254209921

bonus problem

  • Write a function zip_with which zips two lists with a function that you specify
    zip([1,2,3][a,b,c]) => [(1,a), (2,b), (3,c)]
    zip_with(zipper, [1,2,3,4], [1,2,3,4]) => it should combine two lists using zipper function
  • fixed point of a function is value of x such that f(x) = x. one way to find fixed point is to keep applying same function to some starting guess till you reach fixed point. Write a function fixedpoint to find fixed point with given accuracy.
    fixedpoint(cos, guess=1.0, accuracy = 0.00001)
In [244]:
def make_logger(logger_type):
    
    def logger(msg):
        print("[{0}]:{1}".format(logger_type, msg))
        
    return logger
In [245]:
info = make_logger("INFO")
In [246]:
info("process started normally...")
[INFO]:process started normally...
In [247]:
warn = make_logger("WARN")
In [248]:
warn("something went wrong!")
[WARN]:something went wrong!
In [252]:
def zip_with(zipper):
    
    def zipper_(seq1, seq2):
        return [zipper(i,j) for i,j in zip(seq1, seq2)]
    
    return zipper_
In [253]:
vector_adder = zip_with(lambda x,y:x+y)
In [254]:
vector_adder([1,2,3,4],[1,1,1,1])
Out[254]:
[2, 3, 4, 5]
In [258]:
def compose(f, g):
    def fg(x):
        return f(g(x))
    return fg
In [259]:
ssin = compose(square, math.sin)
In [260]:
ssin(math.pi/4)
Out[260]:
0.4999999999999999

Decorators

In [261]:
def add(x,y):
    print("calling func add ", x, y)
    v = x +y 
    print("Returning add ", v)
    return v
In [262]:
def square(x):
    return x*x
In [263]:
square
Out[263]:
<function __main__.square>
In [264]:
def modified_square(x):
    print("calling square", x)
    v = square(x)
    print("returning square", v)
    return v
In [268]:
def debugger(func):
    def modified_func(x):
        print("calling ",func.__name__, x)
        v = func(x)
        print("returning ",func.__name__, v)
        return v
    return modified_func
In [269]:
square_debug = debugger(square)
In [270]:
square_debug(3)
calling  square 3
returning  square 9
Out[270]:
9
In [271]:
square = debugger(square)
In [272]:
square(4)
calling  square 4
returning  square 16
Out[272]:
16
In [273]:
import math
In [274]:
from math import sin
In [275]:
sin(math.pi/4)
Out[275]:
0.7071067811865475
In [276]:
sin = debugger(sin)
In [277]:
sin(math.pi/4)
calling  sin 0.7853981633974483
returning  sin 0.7071067811865475
Out[277]:
0.7071067811865475
In [282]:
@debugger
def double(x): ## same as double = debugger(double)
    return 2*x
In [281]:
double(3)
calling  double 3
returning  double 6
Out[281]:
6
In [283]:
def sub(x,y):
    """
    some help for sub
    """
    return x - y
In [284]:
help(sub)
Help on function sub in module __main__:

sub(x, y)
    some help for sub

In [285]:
help(square)
Help on function modified_func in module __main__:

modified_func(x)

In [288]:
def foo():
    pass
In [289]:
foo.__name__
Out[289]:
'foo'
In [290]:
foo.__qualname__
Out[290]:
'foo'
In [292]:
def decorator(func):
    
    def wrapper(*args):
        print("preproccing")
        r = func(*args)
        print("post processing")
        return r
    
    wrapper

problem

  • Write a decoartor deprecated which prints warning message that given function is deprecated
In [293]:
def deprecated(func):
    
    def wrapper(*args):
        print("Function {} is deprecated!".format(func.__qualname__))
        return func(*args)
    return wrapper
In [294]:
def fib(n):
    if n in [0,1]:
        return 1
    else:
        return fib(n-1) + fib(n-2)
In [299]:
%%file fib.py
import sys

def fib(n):
    if n in [0,1]:
        return 1
    else:
        return fib(n-1) + fib(n-2)
    
if __name__ == "__main__":
    print(fib(int(sys.argv[1])))
Overwriting fib.py
In [300]:
!python fib.py 7
21
In [323]:
%%file trace.py
import os

level = 0

def trace(func):
    
    def log(*args):
        if os.getenv("DEBUG")=="TRUE":
            print(*args)
    
    def wrapper(*args):
        global level 
        
        level += 1
        log("| "*level  + "|--" + func.__name__ , args)
        r = func(*args)
        log("| "*level  + "|-- return " , r)
        level -= 1
        return r
    
    return wrapper
Overwriting trace.py
In [326]:
%%file fib.py
import sys
import trace

@trace.trace
def fib(n):
    if n in [0,1]:
        return 1
    else:
        return fib(n-1) + fib(n-2)
    
if __name__ == "__main__":
    print(fib(int(sys.argv[1])))
Overwriting fib.py
In [320]:
import trace
import imp
imp.reload(trace)
Out[320]:
<module 'trace' from '/home/vikrant/trainings/2018/vmware-advanced-may/trace.py'>
In [321]:
@trace.trace
def square(x):
    return x*x

@trace.trace
def sum_of_squares(x,y):
    return square(x) + square(y)
In [322]:
sum_of_squares(2,3)
| |--sum_of_squares (2, 3)
| | |--square (2,)
| | |-- return  4
| | |--square (3,)
| | |-- return  9
| |-- return  13
Out[322]:
13
In [330]:
!time -p python fib.py 30
1346269
real 21.21
user 21.20
sys 0.00
In [338]:
%%file memoize.py

cache = {}

def memoize(func):
    def wrapper(*args):
        if args not in cache:
            cache[args] = func(*args)
        return cache[args]
    
    return wrapper
            
Overwriting memoize.py
In [346]:
import memoize
import imp
imp.reload(memoize)
Out[346]:
<module 'memoize' from '/home/vikrant/trainings/2018/vmware-advanced-may/memoize.py'>
In [347]:
@memoize.memoize
def square(x):
    print("computing square({})".format(x))
    return x*x
In [348]:
square(2)
computing square(2)
Out[348]:
4
In [349]:
square(2)
Out[349]:
4
In [350]:
%%file fib1.py
import sys
import trace
import memoize

@memoize.memoize
@trace.trace
def fib(n):
    if n in [0,1]:
        return 1
    else:
        return fib(n-1) + fib(n-2)
    
if __name__ == "__main__":
    print(fib(int(sys.argv[1])))
Writing fib1.py
In [351]:
!time -p python fib1.py 30
1346269
real 0.04
user 0.03
sys 0.00
In [354]:
!DEBUG=TRUE python fib1.py 10
| |--fib (10,)
| | |--fib (9,)
| | | |--fib (8,)
| | | | |--fib (7,)
| | | | | |--fib (6,)
| | | | | | |--fib (5,)
| | | | | | | |--fib (4,)
| | | | | | | | |--fib (3,)
| | | | | | | | | |--fib (2,)
| | | | | | | | | | |--fib (1,)
| | | | | | | | | | |-- return  1
| | | | | | | | | | |--fib (0,)
| | | | | | | | | | |-- return  1
| | | | | | | | | |-- return  2
| | | | | | | | |-- return  3
| | | | | | | |-- return  5
| | | | | | |-- return  8
| | | | | |-- return  13
| | | | |-- return  21
| | | |-- return  34
| | |-- return  55
| |-- return  89
89
In [355]:
!DEBUG=TRUE python fib.py 10
| |--fib (10,)
| | |--fib (9,)
| | | |--fib (8,)
| | | | |--fib (7,)
| | | | | |--fib (6,)
| | | | | | |--fib (5,)
| | | | | | | |--fib (4,)
| | | | | | | | |--fib (3,)
| | | | | | | | | |--fib (2,)
| | | | | | | | | | |--fib (1,)
| | | | | | | | | | |-- return  1
| | | | | | | | | | |--fib (0,)
| | | | | | | | | | |-- return  1
| | | | | | | | | |-- return  2
| | | | | | | | | |--fib (1,)
| | | | | | | | | |-- return  1
| | | | | | | | |-- return  3
| | | | | | | | |--fib (2,)
| | | | | | | | | |--fib (1,)
| | | | | | | | | |-- return  1
| | | | | | | | | |--fib (0,)
| | | | | | | | | |-- return  1
| | | | | | | | |-- return  2
| | | | | | | |-- return  5
| | | | | | | |--fib (3,)
| | | | | | | | |--fib (2,)
| | | | | | | | | |--fib (1,)
| | | | | | | | | |-- return  1
| | | | | | | | | |--fib (0,)
| | | | | | | | | |-- return  1
| | | | | | | | |-- return  2
| | | | | | | | |--fib (1,)
| | | | | | | | |-- return  1
| | | | | | | |-- return  3
| | | | | | |-- return  8
| | | | | | |--fib (4,)
| | | | | | | |--fib (3,)
| | | | | | | | |--fib (2,)
| | | | | | | | | |--fib (1,)
| | | | | | | | | |-- return  1
| | | | | | | | | |--fib (0,)
| | | | | | | | | |-- return  1
| | | | | | | | |-- return  2
| | | | | | | | |--fib (1,)
| | | | | | | | |-- return  1
| | | | | | | |-- return  3
| | | | | | | |--fib (2,)
| | | | | | | | |--fib (1,)
| | | | | | | | |-- return  1
| | | | | | | | |--fib (0,)
| | | | | | | | |-- return  1
| | | | | | | |-- return  2
| | | | | | |-- return  5
| | | | | |-- return  13
| | | | | |--fib (5,)
| | | | | | |--fib (4,)
| | | | | | | |--fib (3,)
| | | | | | | | |--fib (2,)
| | | | | | | | | |--fib (1,)
| | | | | | | | | |-- return  1
| | | | | | | | | |--fib (0,)
| | | | | | | | | |-- return  1
| | | | | | | | |-- return  2
| | | | | | | | |--fib (1,)
| | | | | | | | |-- return  1
| | | | | | | |-- return  3
| | | | | | | |--fib (2,)
| | | | | | | | |--fib (1,)
| | | | | | | | |-- return  1
| | | | | | | | |--fib (0,)
| | | | | | | | |-- return  1
| | | | | | | |-- return  2
| | | | | | |-- return  5
| | | | | | |--fib (3,)
| | | | | | | |--fib (2,)
| | | | | | | | |--fib (1,)
| | | | | | | | |-- return  1
| | | | | | | | |--fib (0,)
| | | | | | | | |-- return  1
| | | | | | | |-- return  2
| | | | | | | |--fib (1,)
| | | | | | | |-- return  1
| | | | | | |-- return  3
| | | | | |-- return  8
| | | | |-- return  21
| | | | |--fib (6,)
| | | | | |--fib (5,)
| | | | | | |--fib (4,)
| | | | | | | |--fib (3,)
| | | | | | | | |--fib (2,)
| | | | | | | | | |--fib (1,)
| | | | | | | | | |-- return  1
| | | | | | | | | |--fib (0,)
| | | | | | | | | |-- return  1
| | | | | | | | |-- return  2
| | | | | | | | |--fib (1,)
| | | | | | | | |-- return  1
| | | | | | | |-- return  3
| | | | | | | |--fib (2,)
| | | | | | | | |--fib (1,)
| | | | | | | | |-- return  1
| | | | | | | | |--fib (0,)
| | | | | | | | |-- return  1
| | | | | | | |-- return  2
| | | | | | |-- return  5
| | | | | | |--fib (3,)
| | | | | | | |--fib (2,)
| | | | | | | | |--fib (1,)
| | | | | | | | |-- return  1
| | | | | | | | |--fib (0,)
| | | | | | | | |-- return  1
| | | | | | | |-- return  2
| | | | | | | |--fib (1,)
| | | | | | | |-- return  1
| | | | | | |-- return  3
| | | | | |-- return  8
| | | | | |--fib (4,)
| | | | | | |--fib (3,)
| | | | | | | |--fib (2,)
| | | | | | | | |--fib (1,)
| | | | | | | | |-- return  1
| | | | | | | | |--fib (0,)
| | | | | | | | |-- return  1
| | | | | | | |-- return  2
| | | | | | | |--fib (1,)
| | | | | | | |-- return  1
| | | | | | |-- return  3
| | | | | | |--fib (2,)
| | | | | | | |--fib (1,)
| | | | | | | |-- return  1
| | | | | | | |--fib (0,)
| | | | | | | |-- return  1
| | | | | | |-- return  2
| | | | | |-- return  5
| | | | |-- return  13
| | | |-- return  34
| | | |--fib (7,)
| | | | |--fib (6,)
| | | | | |--fib (5,)
| | | | | | |--fib (4,)
| | | | | | | |--fib (3,)
| | | | | | | | |--fib (2,)
| | | | | | | | | |--fib (1,)
| | | | | | | | | |-- return  1
| | | | | | | | | |--fib (0,)
| | | | | | | | | |-- return  1
| | | | | | | | |-- return  2
| | | | | | | | |--fib (1,)
| | | | | | | | |-- return  1
| | | | | | | |-- return  3
| | | | | | | |--fib (2,)
| | | | | | | | |--fib (1,)
| | | | | | | | |-- return  1
| | | | | | | | |--fib (0,)
| | | | | | | | |-- return  1
| | | | | | | |-- return  2
| | | | | | |-- return  5
| | | | | | |--fib (3,)
| | | | | | | |--fib (2,)
| | | | | | | | |--fib (1,)
| | | | | | | | |-- return  1
| | | | | | | | |--fib (0,)
| | | | | | | | |-- return  1
| | | | | | | |-- return  2
| | | | | | | |--fib (1,)
| | | | | | | |-- return  1
| | | | | | |-- return  3
| | | | | |-- return  8
| | | | | |--fib (4,)
| | | | | | |--fib (3,)
| | | | | | | |--fib (2,)
| | | | | | | | |--fib (1,)
| | | | | | | | |-- return  1
| | | | | | | | |--fib (0,)
| | | | | | | | |-- return  1
| | | | | | | |-- return  2
| | | | | | | |--fib (1,)
| | | | | | | |-- return  1
| | | | | | |-- return  3
| | | | | | |--fib (2,)
| | | | | | | |--fib (1,)
| | | | | | | |-- return  1
| | | | | | | |--fib (0,)
| | | | | | | |-- return  1
| | | | | | |-- return  2
| | | | | |-- return  5
| | | | |-- return  13
| | | | |--fib (5,)
| | | | | |--fib (4,)
| | | | | | |--fib (3,)
| | | | | | | |--fib (2,)
| | | | | | | | |--fib (1,)
| | | | | | | | |-- return  1
| | | | | | | | |--fib (0,)
| | | | | | | | |-- return  1
| | | | | | | |-- return  2
| | | | | | | |--fib (1,)
| | | | | | | |-- return  1
| | | | | | |-- return  3
| | | | | | |--fib (2,)
| | | | | | | |--fib (1,)
| | | | | | | |-- return  1
| | | | | | | |--fib (0,)
| | | | | | | |-- return  1
| | | | | | |-- return  2
| | | | | |-- return  5
| | | | | |--fib (3,)
| | | | | | |--fib (2,)
| | | | | | | |--fib (1,)
| | | | | | | |-- return  1
| | | | | | | |--fib (0,)
| | | | | | | |-- return  1
| | | | | | |-- return  2
| | | | | | |--fib (1,)
| | | | | | |-- return  1
| | | | | |-- return  3
| | | | |-- return  8
| | | |-- return  21
| | |-- return  55
| | |--fib (8,)
| | | |--fib (7,)
| | | | |--fib (6,)
| | | | | |--fib (5,)
| | | | | | |--fib (4,)
| | | | | | | |--fib (3,)
| | | | | | | | |--fib (2,)
| | | | | | | | | |--fib (1,)
| | | | | | | | | |-- return  1
| | | | | | | | | |--fib (0,)
| | | | | | | | | |-- return  1
| | | | | | | | |-- return  2
| | | | | | | | |--fib (1,)
| | | | | | | | |-- return  1
| | | | | | | |-- return  3
| | | | | | | |--fib (2,)
| | | | | | | | |--fib (1,)
| | | | | | | | |-- return  1
| | | | | | | | |--fib (0,)
| | | | | | | | |-- return  1
| | | | | | | |-- return  2
| | | | | | |-- return  5
| | | | | | |--fib (3,)
| | | | | | | |--fib (2,)
| | | | | | | | |--fib (1,)
| | | | | | | | |-- return  1
| | | | | | | | |--fib (0,)
| | | | | | | | |-- return  1
| | | | | | | |-- return  2
| | | | | | | |--fib (1,)
| | | | | | | |-- return  1
| | | | | | |-- return  3
| | | | | |-- return  8
| | | | | |--fib (4,)
| | | | | | |--fib (3,)
| | | | | | | |--fib (2,)
| | | | | | | | |--fib (1,)
| | | | | | | | |-- return  1
| | | | | | | | |--fib (0,)
| | | | | | | | |-- return  1
| | | | | | | |-- return  2
| | | | | | | |--fib (1,)
| | | | | | | |-- return  1
| | | | | | |-- return  3
| | | | | | |--fib (2,)
| | | | | | | |--fib (1,)
| | | | | | | |-- return  1
| | | | | | | |--fib (0,)
| | | | | | | |-- return  1
| | | | | | |-- return  2
| | | | | |-- return  5
| | | | |-- return  13
| | | | |--fib (5,)
| | | | | |--fib (4,)
| | | | | | |--fib (3,)
| | | | | | | |--fib (2,)
| | | | | | | | |--fib (1,)
| | | | | | | | |-- return  1
| | | | | | | | |--fib (0,)
| | | | | | | | |-- return  1
| | | | | | | |-- return  2
| | | | | | | |--fib (1,)
| | | | | | | |-- return  1
| | | | | | |-- return  3
| | | | | | |--fib (2,)
| | | | | | | |--fib (1,)
| | | | | | | |-- return  1
| | | | | | | |--fib (0,)
| | | | | | | |-- return  1
| | | | | | |-- return  2
| | | | | |-- return  5
| | | | | |--fib (3,)
| | | | | | |--fib (2,)
| | | | | | | |--fib (1,)
| | | | | | | |-- return  1
| | | | | | | |--fib (0,)
| | | | | | | |-- return  1
| | | | | | |-- return  2
| | | | | | |--fib (1,)
| | | | | | |-- return  1
| | | | | |-- return  3
| | | | |-- return  8
| | | |-- return  21
| | | |--fib (6,)
| | | | |--fib (5,)
| | | | | |--fib (4,)
| | | | | | |--fib (3,)
| | | | | | | |--fib (2,)
| | | | | | | | |--fib (1,)
| | | | | | | | |-- return  1
| | | | | | | | |--fib (0,)
| | | | | | | | |-- return  1
| | | | | | | |-- return  2
| | | | | | | |--fib (1,)
| | | | | | | |-- return  1
| | | | | | |-- return  3
| | | | | | |--fib (2,)
| | | | | | | |--fib (1,)
| | | | | | | |-- return  1
| | | | | | | |--fib (0,)
| | | | | | | |-- return  1
| | | | | | |-- return  2
| | | | | |-- return  5
| | | | | |--fib (3,)
| | | | | | |--fib (2,)
| | | | | | | |--fib (1,)
| | | | | | | |-- return  1
| | | | | | | |--fib (0,)
| | | | | | | |-- return  1
| | | | | | |-- return  2
| | | | | | |--fib (1,)
| | | | | | |-- return  1
| | | | | |-- return  3
| | | | |-- return  8
| | | | |--fib (4,)
| | | | | |--fib (3,)
| | | | | | |--fib (2,)
| | | | | | | |--fib (1,)
| | | | | | | |-- return  1
| | | | | | | |--fib (0,)
| | | | | | | |-- return  1
| | | | | | |-- return  2
| | | | | | |--fib (1,)
| | | | | | |-- return  1
| | | | | |-- return  3
| | | | | |--fib (2,)
| | | | | | |--fib (1,)
| | | | | | |-- return  1
| | | | | | |--fib (0,)
| | | | | | |-- return  1
| | | | | |-- return  2
| | | | |-- return  5
| | | |-- return  13
| | |-- return  34
| |-- return  89
89
In [ ]: