Python Training at VMWare - Day 2

Jan 29-31, 2018 Vikrant Patil

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

© Pipal Academy LLP

Day 1 | Day 2 | Day 3

In [1]:
for i in range(10):
    print(i, end=",")
0,1,2,3,4,5,6,7,8,9,
In [7]:
def print_primes(n):
    """
    print primes less than n
    """
    for i in range(2,n):
        for j in range(2,i):
            if i%j==0:
                break
        else:
            print(i, end=",")
    
        
In [8]:
print_primes(20)
2,3,5,7,11,13,17,19,
In [5]:
for i in range(1,20):
    flag = True
    for j in range(2,i):
        if i%j==0:
            flag = False
            break
    if flag:
        print(i, end=",")
1,2,3,5,7,11,13,17,19,
In [6]:
list(range(2,1))
Out[6]:
[]
In [9]:
list(range(10)) #starts at 0 and ends at 9 at step of 1
Out[9]:
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
In [10]:
list(range(2,10)) #starts at 2 ends at 9 at step of 1
Out[10]:
[2, 3, 4, 5, 6, 7, 8, 9]
In [11]:
list(range(1,10,2)) # starts at 1 ends at 9 at step of 2
Out[11]:
[1, 3, 5, 7, 9]
In [12]:
def print_fibonacci(n):
    """
    prints fibonnaci numbers less than n
    """
    prev, current = 1, 1
    while current < n:
        print(current, end=",")
        prev, current = current, prev+current
        

problem

  • Modify fibonacci function to print fibinacci numbers that are prime.
In [14]:
def is_prime(n):
    for j in range(2,n):
        if n%j==0:
            return False
    return True
        
def print_prime_fibonacci(n):
    """
    prints fibonnaci numbers less than n
    """
    prev, current = 1, 1
    while current < n:
        if is_prime(current):
            print(current, end=",")
        prev, current = current, prev+current   
        

                        
In [15]:
print_prime_fibonacci(100)
1,2,3,5,13,89,

Recap lists methods

In [16]:
digits = list(range(10))
In [17]:
digits
Out[17]:
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
In [18]:
digits.append(10)
In [19]:
digits.insert(0, -1)
In [20]:
digits.pop()
Out[20]:
10
In [22]:
digits.pop(0)
Out[22]:
-1
In [23]:
empty = []
In [24]:
digits[0]
Out[24]:
0
In [25]:
digits
Out[25]:
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
In [26]:
twice = []
for number in digits:
    twice.append(2*number)
    
In [27]:
twice
Out[27]:
[0, 2, 4, 6, 8, 10, 12, 14, 16, 18]

problems

  • Write a function squarelist which returns a new list which is square of every item of original list
  • Write a function evens which returns only even numbers from given lists
In [28]:
def squarelist(items):
    squares = []
    for item in items:
        squares.append(item**2)
    return squares

def evens(items):
    def even(n):
        return n%2==0
    
    e = []
    for item in items:
        if even(item):
            e.append(item)
    return e
In [29]:
squarelist(digits)
Out[29]:
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
In [30]:
evens(digits)
Out[30]:
[0, 2, 4, 6, 8]

lists comprehensions

p = []
for item in seq:
    newitem = do_some_processing(item)
    p.append(newitem)
[do_some_processing(item) for item in seq]
[item for item in seq if condition(item)]
[do_some_processing(item) for item in seq if condition(item)]
In [31]:
[x*x for x in digits]
Out[31]:
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
In [32]:
def cube(x):
    return x*x*x
[cube(item) for item in digits]
Out[32]:
[0, 1, 8, 27, 64, 125, 216, 343, 512, 729]
In [33]:
[cube(item) for item in digits if item%2==0]
Out[33]:
[0, 8, 64, 216, 512]

problems

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

bonus problem

  • find sum of all multiples of 7 or 11 below 1000
In [34]:
def say_hello(name):
    return "hello " + name

persons = ["kavya","kavita","kavi","krishna"]

[say_hello(p) for p in persons if p.endswith("i")]

[p for p in persons if p.endswith("a")]
Out[34]:
['kavya', 'kavita', 'krishna']
In [35]:
import os
def listpy(path):
    return [file for file in os.listdir(path) if file.endswith(".py")]
In [36]:
listpy(os.getcwd())
Out[36]:
['product.py',
 'myscript.py',
 'square3.py',
 'echo.py',
 'mysum.py',
 'square.py',
 'hello.py',
 'hello2.py',
 'mymodule.py',
 'hello1.py',
 'hello3.py',
 'yes.py',
 'ls.py',
 'square1.py']
In [37]:
def factors(n):
    return [i for i in range(1,n+1) if n%i==0]
In [38]:
factors(5)
Out[38]:
[1, 5]
In [39]:
factors(25)
Out[39]:
[1, 5, 25]
In [40]:
def is_prime(n):
    return factors(n)==[1,n]
In [41]:
is_prime(5)
Out[41]:
True
In [43]:
[p for p in range(50) if is_prime(p)]
Out[43]:
[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47]
In [45]:
t = [[i*j for i in range(1,10)]  for j in range(1,6)]
In [46]:
t
Out[46]:
[[1, 2, 3, 4, 5, 6, 7, 8, 9],
 [2, 4, 6, 8, 10, 12, 14, 16, 18],
 [3, 6, 9, 12, 15, 18, 21, 24, 27],
 [4, 8, 12, 16, 20, 24, 28, 32, 36],
 [5, 10, 15, 20, 25, 30, 35, 40, 45]]
In [47]:
t[0]
Out[47]:
[1, 2, 3, 4, 5, 6, 7, 8, 9]
In [48]:
t[-1]
Out[48]:
[5, 10, 15, 20, 25, 30, 35, 40, 45]

problem

  • generate unit symmetric matrix of dimention 5x5 using list comprehension. unit matix is a matrix with diagonals as 1 and all other elements as zero
In [49]:
def equal(x,y):
    if x==y:
        return 1
    else:
        return 0
    
[[equal(i,j) for i in range(5)] for j in range(5)]
Out[49]:
[[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 [50]:
[[int(i==j) for i in range(5)] for j in range(5)]
Out[50]:
[[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 [52]:
[[{True:1,False:0}[i==j] for i in range(5)] for j in range(5)]
Out[52]:
[[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 [53]:
sum([i for i in range(1000) if i%7==0 or i%11==0])
Out[53]:
110110
In [54]:
t
Out[54]:
[[1, 2, 3, 4, 5, 6, 7, 8, 9],
 [2, 4, 6, 8, 10, 12, 14, 16, 18],
 [3, 6, 9, 12, 15, 18, 21, 24, 27],
 [4, 8, 12, 16, 20, 24, 28, 32, 36],
 [5, 10, 15, 20, 25, 30, 35, 40, 45]]
In [55]:
t[0] # 0th row
Out[55]:
[1, 2, 3, 4, 5, 6, 7, 8, 9]
In [56]:
t[0][0] # 0th row , 0th col
Out[56]:
1
In [57]:
rowcount = len(t)
In [59]:
[t[i][0] for i in range(rowcount)] # 0th column
Out[59]:
[1, 2, 3, 4, 5]
In [60]:
def column(data, n):
    rowcount = len(data)
    return [data[i][n] for i in range(rowcount)]
In [62]:
column(t, 0)
Out[62]:
[1, 2, 3, 4, 5]
In [63]:
column(t, 1)
Out[63]:
[2, 4, 6, 8, 10]
In [64]:
t
Out[64]:
[[1, 2, 3, 4, 5, 6, 7, 8, 9],
 [2, 4, 6, 8, 10, 12, 14, 16, 18],
 [3, 6, 9, 12, 15, 18, 21, 24, 27],
 [4, 8, 12, 16, 20, 24, 28, 32, 36],
 [5, 10, 15, 20, 25, 30, 35, 40, 45]]
In [65]:
def transpose(data):
    columncount = len(data[0])
    return [column(data, i) for i in range(columncount)]
In [66]:
transpose(t)
Out[66]:
[[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]]
In [67]:
t
Out[67]:
[[1, 2, 3, 4, 5, 6, 7, 8, 9],
 [2, 4, 6, 8, 10, 12, 14, 16, 18],
 [3, 6, 9, 12, 15, 18, 21, 24, 27],
 [4, 8, 12, 16, 20, 24, 28, 32, 36],
 [5, 10, 15, 20, 25, 30, 35, 40, 45]]

problem

  • rotate 2d matrix by 90 degree clockwise.
  • rotate 2d matrix by 90 degree anticlockwise
In [68]:
list(range(10))
Out[68]:
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
In [69]:
[i for i in range(10)]
Out[69]:
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
In [70]:
[10-i for i in range(10)]
Out[70]:
[10, 9, 8, 7, 6, 5, 4, 3, 2, 1]
In [72]:
list(range(0,10,-1))
Out[72]:
[]
In [77]:
def reverse(seq):
    n = len(seq)
    return [seq[n-i-1] for i in range(n)]
    
def rotateclockwise(data):
    colcount = len(data[0])
    return [reverse(column(data, i)) for i in range(colcount)]
In [78]:
list(range(10,-1,-1))
Out[78]:
[10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
In [79]:
rotateclockwise(t)
Out[79]:
[[5, 4, 3, 2, 1],
 [10, 8, 6, 4, 2],
 [15, 12, 9, 6, 3],
 [20, 16, 12, 8, 4],
 [25, 20, 15, 10, 5],
 [30, 24, 18, 12, 6],
 [35, 28, 21, 14, 7],
 [40, 32, 24, 16, 8],
 [45, 36, 27, 18, 9]]
In [80]:
t
Out[80]:
[[1, 2, 3, 4, 5, 6, 7, 8, 9],
 [2, 4, 6, 8, 10, 12, 14, 16, 18],
 [3, 6, 9, 12, 15, 18, 21, 24, 27],
 [4, 8, 12, 16, 20, 24, 28, 32, 36],
 [5, 10, 15, 20, 25, 30, 35, 40, 45]]
In [81]:
def rotateanticlockwise(data):
    colcount = len(data[0])
    return [column(data, i) for i in range(colcount-1, -1, -1)]
In [83]:
rotateanticlockwise(t)
Out[83]:
[[9, 18, 27, 36, 45],
 [8, 16, 24, 32, 40],
 [7, 14, 21, 28, 35],
 [6, 12, 18, 24, 30],
 [5, 10, 15, 20, 25],
 [4, 8, 12, 16, 20],
 [3, 6, 9, 12, 15],
 [2, 4, 6, 8, 10],
 [1, 2, 3, 4, 5]]
In [84]:
[reverse(column(t,i)) for i in range(len(t[0]))]
Out[84]:
[[5, 4, 3, 2, 1],
 [10, 8, 6, 4, 2],
 [15, 12, 9, 6, 3],
 [20, 16, 12, 8, 4],
 [25, 20, 15, 10, 5],
 [30, 24, 18, 12, 6],
 [35, 28, 21, 14, 7],
 [40, 32, 24, 16, 8],
 [45, 36, 27, 18, 9]]

Example

Quicksort

[3,6,1,2,8,9]

p = 3 less = [1,2] greater = [6,8,9]

quick(less) + [p] + quick(greater)

In [85]:
def quick(items):
    if not items:
        return []
    
    pivot = items[0]
    less_ = [i for i in items[1:] if i < pivot]
    greater_ = [i for i in items[1:] if i >= pivot]
    
    return quick(less_) + [pivot] + quick(greater_)
In [86]:
quick([2,3,4,1,1,2,37,1,2,1])
Out[86]:
[1, 1, 1, 1, 2, 2, 2, 3, 4, 37]
In [89]:
import matplotlib.pyplot as plt
%matplotlib inline
def imshow(img):
    plt.imshow(img, cmap=plt.cm.gray)
    plt.show()
In [90]:
imshow(t)
In [91]:
imshow(rotateanticlockwise(t))
In [92]:
imshow(rotateclockwise(t))

problem

  • Kaprekar iteration - you take a number find digits, reaarange them and two numbers smallest and largest. substract smallest from largest. you get new number. perform same operation on this new number.
In [95]:
def rearrangemax(n):
    strn = str(n)
    return int("".join(sorted(strn, reverse=True)))

def rearrangemin(n):
    strn = str(n)
    return int("".join(sorted(strn)))

def kaprekar(n, iters=50):
    for i in range(iters):
        min_ = rearrangemin(n)
        max_ = rearrangemax(n)
        n  = max_ - min_
    
    return n
In [96]:
kaprekar(2345)
Out[96]:
6174

list slicing

slicing works on lists, string, tuples

In [97]:
digits = list(range(10))
In [98]:
digits
Out[98]:
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
In [99]:
digits[2:5:1] # start at 2nd index , end at 5th index(excluding) at interval of 1
Out[99]:
[2, 3, 4]
In [100]:
digits
Out[100]:
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
In [101]:
digits[:5] #first five
Out[101]:
[0, 1, 2, 3, 4]
In [102]:
digits[5:] # drop frist five
Out[102]:
[5, 6, 7, 8, 9]
In [104]:
digits[:] # copy
Out[104]:
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
In [107]:
digits[:-1] # all except last.. drop last one
Out[107]:
[0, 1, 2, 3, 4, 5, 6, 7, 8]
In [108]:
digits[:-3]# drop last 3
Out[108]:
[0, 1, 2, 3, 4, 5, 6]
In [110]:
digits[::-1] # reverse
Out[110]:
[9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
In [111]:
word = "madam"
In [112]:
f = lambda x: x*x
In [113]:
f(3)
Out[113]:
9
In [114]:
is_palindrom = lambda w: w==w[::-1]
In [115]:
is_palindrom(word)
Out[115]:
True
In [116]:
even = lambda x : x%2==0
In [117]:
even(4)
Out[117]:
True
In [118]:
odd = lambda x: not even(x)
In [119]:
odd(3)
Out[119]:
True

problem

  • use slicing to write a function split_at which splits given list in two lists at given index
  • write a function find_extension to find extension of given file.
In [125]:
def pair(x,y):
    return 2*x, 2*y # function can return multiple values
In [121]:
pair(1,2)
Out[121]:
(2, 4)
In [124]:
add = lambda x,y:x+y # lambda can take multiple parameters
In [126]:
add(2,3)
Out[126]:
5
In [129]:
f = lambda x: (x,x**2,x**3) 
In [130]:
f(2)
Out[130]:
(2, 4, 8)
In [131]:
def split_at(seq, index):
    return seq[:n],seq[n:]
In [132]:
def find_extension(filename):
    return filename.split(".")[-1]
In [133]:
"hello.tar.gz".split(".")
Out[133]:
['hello', 'tar', 'gz']
In [134]:
s = "do gees see god"
In [135]:
s[100]
---------------------------------------------------------------------------
IndexError                                Traceback (most recent call last)
<ipython-input-135-4868bd16d438> in <module>()
----> 1 s[100]

IndexError: string index out of range
In [136]:
s[:100]
Out[136]:
'do gees see god'

Iteration patterns

In [137]:
for n in digits:
    print(n, end=",")
0,1,2,3,4,5,6,7,8,9,
In [138]:
for n in reversed(digits):
    print(n, end=",")
9,8,7,6,5,4,3,2,1,0,
In [139]:
r = reversed(digits)
In [140]:
for i in r:
    print(i, end=",")
9,8,7,6,5,4,3,2,1,0,
In [141]:
for i in r:
    print(i, end=",")
In [142]:
r = list(reversed(digits))
In [143]:
r
Out[143]:
[9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
In [144]:
range(10)
Out[144]:
range(0, 10)
In [147]:
for index, item in enumerate(r):
    print(index, item)
0 9
1 8
2 7
3 6
4 5
5 4
6 3
7 2
8 1
9 0
In [148]:
r = range(5)
In [150]:
for i in r:
    print(i)
0
1
2
3
4
In [151]:
for i in r:
    print(i)
0
1
2
3
4
In [152]:
r
Out[152]:
range(0, 5)
In [153]:
digits = [1,2,3,4,5]
letter = ["A","B","C","D","E"]
In [154]:
for d,l in zip(digits, letter):
    print(d, l)
1 A
2 B
3 C
4 D
5 E
In [155]:
digits = [1,2,3]
letter = ["A","B","C","D","E"]
In [157]:
list(zip([1,2],['a','b'],['x','y']))
Out[157]:
[(1, 'a', 'x'), (2, 'b', 'y')]
In [158]:
for d,l in zip(digits, letter):
    print(d, l)
1 A
2 B
3 C

problem

  • Write a function vector_add, which does vector addition of two vectors taken as list

bonus problem

  • Can you write a function zip_with which zips two lists with given operation?
In [159]:
def vector_add(vector1, vector2):
    return [x+y for x,y in zip(vector1, vector2)]
In [160]:
def zip_with(f, v1, v2):
    return [f(x,y) for x,y in zip(v1, v2)]
In [161]:
vector_add(range(5), range(5))
Out[161]:
[0, 2, 4, 6, 8]
In [162]:
zip_with(lambda x,y:x+y, range(5), range(5))
Out[162]:
[0, 2, 4, 6, 8]
In [163]:
zip_with(lambda x,y:x*y, range(5), range(5))
Out[163]:
[0, 1, 4, 9, 16]
In [168]:
%%file functions.py

def eval_poly(coeffs, x):
    s = 0
    n = len(coeffs)-1
    for i, c in enumerate(coeffs):
        s += c* x**(n-i)
    return s

def eval_poly1(coeffs, x):
    s = 0
    
    for i,c in enumerate(reversed(coeffs)):
        s += c*x**i
        
    return s


def test_poly():
    ### [1,1,1] => x^2 + x + 1
    coeffs = [1,1,1]
    assert eval_poly(coeffs, 0)==1
    assert eval_poly(coeffs, 1)==3
    assert eval_poly([1,0,1], 2)==5
    
    
    
    
Overwriting functions.py
In [171]:
!py.test -v functions.py 
============================= test session starts ==============================
platform linux -- Python 3.6.1, pytest-3.0.7, py-1.4.33, pluggy-0.4.0 -- /home/vikrant/usr/local/anaconda3/bin/python
cachedir: .cache
rootdir: /home/vikrant/trainings/2018/vmware-pune-jan-python, inifile:
collected 1 items 

functions.py::test_poly PASSED

=========================== 1 passed in 0.00 seconds ===========================
In [166]:
0**1
Out[166]:
0
In [167]:
0**0
Out[167]:
1

String formatting

In [172]:
for i in range(1,11):
    print(i, i**2, i**3)
1 1 1
2 4 8
3 9 27
4 16 64
5 25 125
6 36 216
7 49 343
8 64 512
9 81 729
10 100 1000
In [173]:
for i in range(1,11):
    print(str(i).rjust(2), str(i**2).rjust(3), str(i**3).rjust(4))
 1   1    1
 2   4    8
 3   9   27
 4  16   64
 5  25  125
 6  36  216
 7  49  343
 8  64  512
 9  81  729
10 100 1000
In [174]:
"wizard of {} is {}".format("oz","python")
Out[174]:
'wizard of oz is python'
In [175]:
"wizard of {1} is {0}".format("oz","python")
Out[175]:
'wizard of python is oz'
In [176]:
"purpose of life is {answer}, my computation in {who} says so!".format(answer=42, who="python")
Out[176]:
'purpose of life is 42, my computation in python says so!'
In [179]:
for i in range(1,11):
    print("{num:2d} {sqr:3d} {cube:4d}".format(num=i, sqr=i*i, cube=i**3))
 1   1    1
 2   4    8
 3   9   27
 4  16   64
 5  25  125
 6  36  216
 7  49  343
 8  64  512
 9  81  729
10 100 1000
In [180]:
"{num:{digits}d}".format(num=200,digits=3)
Out[180]:
'200'

problem

  • write a function to generate pascal triangle as list of lists. ```
             1
           1   1
         1   2   1
       1   3    3   1

[[1],[1,1],[1,2,1],[1,3,3,1]

```

  • Write a function to prety print pascal triangle.
In [181]:
"hello".center(50)
Out[181]:
'                      hello                       '
In [182]:
"hello".ljust(10)
Out[182]:
'hello     '
In [183]:
"23".zfill(10)
Out[183]:
'0000000023'
In [185]:
base = [1,2,1]
[1] + [base[i]+base[i+1] for i in range(len(base)-1)] + [1]
Out[185]:
[1, 3, 3, 1]
In [188]:
def pascal(n):
    t = [[1]]
    for i in range(1,n):
        base = t[-1]
        pre = [0] + base
        post = base + [0]
        newbase = [x+y for x,y in zip(pre,post)]
        t.append(newbase)
    return t
In [189]:
pascal(4)
Out[189]:
[[1], [1, 1], [1, 2, 1], [1, 3, 3, 1]]
In [190]:
def pascal(n):
    t = [[1]]
    for i in range(1,n):
        base = t[-1]
        newbase = [1]  + [base[i]+base[i+1] for i in range(len(base)-1)] + [1]
        t.append(newbase)
    return t
In [191]:
pascal(4)
Out[191]:
[[1], [1, 1], [1, 2, 1], [1, 3, 3, 1]]
In [211]:
def print_pascal(t):
    def format_row(row):
        s = ""
        for n in row:
            s += "{num:{digits}d} ".format(num=n, digits=maxdigits)
        return s
    
    maxdigits = len(str(max(t[-1])))
    basesize = len(t[-1])
    width = maxdigits*basesize + basesize-1
    
    for row in t:
        r = format_row(row)
        print(r.center(width))
        
In [215]:
trianlge = pascal(12)
print_pascal(trianlge)
                        1                      
                      1   1                    
                    1   2   1                  
                  1   3   3   1                
                1   4   6   4   1              
              1   5  10  10   5   1            
            1   6  15  20  15   6   1          
          1   7  21  35  35  21   7   1        
        1   8  28  56  70  56  28   8   1      
      1   9  36  84 126 126  84  36   9   1    
    1  10  45 120 210 252 210 120  45  10   1  
  1  11  55 165 330 462 462 330 165  55  11   1 

Working with files

In [216]:
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 [217]:
%%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 [218]:
filehandle = open("data.txt")
In [219]:
filehandle.read()
Out[219]:
"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!\n"
In [220]:
filehandle.read()
Out[220]:
''
In [221]:
filehandle.close()
In [232]:
f = open("data.txt")
In [233]:
f.readline() #read only one line ...line is by default appended with \n
Out[233]:
'The Zen of Python, by Tim Peters\n'
In [234]:
f.readline()
Out[234]:
'\n'
In [235]:
f.readline()
Out[235]:
'Beautiful is better than ugly.\n'
In [236]:
line = f.readline()
while line:
    line = f.readline()
    print(line, end="")
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 [241]:
f = open("data.txt")
In [242]:
f.readline()
Out[242]:
'The Zen of Python, by Tim Peters\n'
In [243]:
f.readline() ##this is empty line...
Out[243]:
'\n'
In [244]:
line = f.readline()
while line:
    line = f.readline()
    print(line)
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 [245]:
f = open("data.txt")
In [246]:
for line in f.readlines():
    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 [248]:
f = open("data.txt")
for index,line in enumerate(f.readlines()):
    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 [249]:
for line in open("data.txt"):
    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!

problem

  • write a python script cat.py which implements unix command cat approximately.
  • Write a python script head.py which implements unix command head approximately.
  • Write a python script wc.py which implemtns unix command wc
In [250]:
%%file cat.py
import sys

def cat(file):
    print(open(file).read())
    
if __name__=="__main__":
    for file in sys.argv[1:]:
        cat(file)
Writing cat.py
In [251]:
!python cat.py hello.py functions.py data.txt
import sys

def say_hello(name):
    print("Hello",name)
    
print(sys.argv)    
    
say_hello(sys.argv[1])

def eval_poly(coeffs, x):
    s = 0
    n = len(coeffs)-1
    for i, c in enumerate(coeffs):
        s += c* x**(n-i)
    return s

def eval_poly1(coeffs, x):
    s = 0
    
    for i,c in enumerate(reversed(coeffs)):
        s += c*x**i
        
    return s


def test_poly():
    ### [1,1,1] => x^2 + x + 1
    coeffs = [1,1,1]
    assert eval_poly(coeffs, 0)==1
    assert eval_poly(coeffs, 1)==3
    assert eval_poly([1,0,1], 2)==5
    
    
    
    
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 [ ]:
 
In [256]:
%%file head.py
import sys

def head(filename, n):
    f = open(filename)
    for i in range(n):
        print(f.readline(),end="")

if __name__ == "__main__":    
    head(sys.argv[2], int(sys.argv[1]))
Overwriting head.py
In [257]:
!python head.py 5 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 [258]:
%%file wc.py
import sys

def count_words(file):
    return len(open(file).read().split())

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

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


if __name__ == "__main__":
    file = sys.argv[1]
    print(count_lines(file), count_words(file), count_chars(file), file)
Writing wc.py
In [259]:
!python wc.py data.txt
21 144 857 data.txt

problem

  • find a file with max number of lines
  • find a file with max number of words?
In [261]:
!python wc.py day1.html
23393 53959 566049 day1.html
In [262]:
!python wc.py day1.ipynb
8615 23478 216370 day1.ipynb
In [263]:
!python wc.py day2.html
17317 40589 427352 day2.html
In [267]:
import os
[filename for filename in os.listdir(os.getcwd()) if os.path.isfile(filename)]
Out[267]:
['wc.py',
 'push',
 'day1.ipynb',
 'head.py',
 'product.py',
 'myscript.py',
 'square3.py',
 'day2.ipynb',
 'echo.py',
 'day2.html',
 'mysum.py',
 'square.py',
 'hello.py',
 'hello2.py',
 'mymodule.py',
 'hello1.py',
 'functions.py',
 'data.txt',
 'hello3.py',
 'Makefile',
 'cat.py',
 'day1.html',
 'yes.py',
 'ls.py',
 'square1.py']
In [268]:
files = [f for f in os.listdir(os.getcwd()) if os.path.isfile(f)]
In [269]:
import wc
In [270]:
max(files, key=wc.count_lines)
Out[270]:
'day1.html'
In [271]:
max(files, key=wc.count_words)
Out[271]:
'day1.html'

debuging

In [272]:
def add(x,y):
    return x+y
In [273]:
def debug_add(x,y):
    print("before add", x, y)
    r = add(x,y)
    print("after add", r)
    return r
In [274]:
def debug(f, *args):
    print("before ", f, *args)
    r = f(*args)
    print("after ",f, r)
    return r
In [275]:
debug(add, 2,3)
before  <function add at 0x7f10151f1048> 2 3
after  <function add at 0x7f10151f1048> 5
Out[275]:
5
In [277]:
def debug(f):
    def wrapper(*args):
        print("before ", f, *args)
        r = f(*args)
        print("after ",f, r)
        return r
    return wrapper
In [278]:
add = debug(add)
In [279]:
add(2,3)
before  <function add at 0x7f10151f1048> 2 3
after  <function add at 0x7f10151f1048> 5
Out[279]:
5
In [ ]: