Nov 15-17, 2017 Vikrant Patil
These notes are available online at http://notes.pipal.in/2017/arcesium-oct-advpython/day1.html
© Pipal Academy LLP
4 + 2.0 # basic data types
4 ** 100
5 / 2
5 // 2
"There" "are" "strings"
"you" + "can" + "add" + "strings"
"stings with ' quote"
'string with " quite'
multi = """
this is
multi
line
string
"""
print(multi)
digits = list(range(10))
digits
digits[0]
digits[9]
digits[-1]
digits[-2]
digits[1:6] #sublist which starts at index 1 (inclusive) and ends at index 6(exlusive)
digits[2:]
digits[:6]
digits[:-1] # all items except last
digits[:] # copy
digits[2:7:2] # elements from index 2 till 7 with step of 2
digits[::-1] # reverse
All the indexing and slicing techniques work with strings too!
word = "madam"
word == word[::-1]
numbers = list(range(2,20,3))
numbers
[n*n for n in numbers]
[n*n*n for n in numbers]
words = "some sentence with some words in it".split()
words
[word.upper() for word in words]
[i for i in range(20) if i%2 == 0] #even numbers
"it" is "not english"
"hell" in "hello"
person = {
"name":"Alice",
"email":"alice@example.com",
"roles":["Admin", "Staff"]
}
person['name']
person["email"]
[key for key in person.keys()]
[v for v in person.values() ]
[(k,v) for k,v in person.items()]
def quicksort(numbers):
def morethan(tail, pivot):
return [x for x in tail if x>=pivot]
def lessthan(tail, pivot):
return [x for x in tail if x<pivot]
if numbers:
pivot = numbers[0]
tail = numbers[1:]
less = lessthan(tail, pivot)
more = morethan(tail, pivot)
return quicksort(less)+ [pivot] + quicksort(more)
else:
return []
quicksort([4,2,6,7,8,20,100,80,3])
%%file data.csv
A1,B1,C1
A2,B2,C2
A3,B3,C3
A4,B4,C4
lines = open("data.csv").readlines()
lines
[line.strip().split(",") for line in lines]
data = [line.strip().split(",") for line in lines]
data
data[-1][0] #last row first element
def cylinder_volume(radius, height):
return 3.14*radius*radius*height
cylinder_volume(5,10)#radius first or height first?
cylinder_volume(10,5)# if you give arguments in wrong order, result will be wrong..it
#is difficult to debug
cylinder_volume(5, height=10)
cylinder_volume(radius=5, height=10)
cylinder_volume(radius=5,10)
import os
def location(name, home="/home/vikrant"):
"""
returns virtual environment root directory
"""
return os.path.sep.join([home, "usr","local", name])
location("jupyter")
location("jupyter", home="/home/anand")
import random
def number():
return random.random()
def func(a, b=number()):
print(a,b)
for i in range(5):
func(i)
def func(a, b=None):
if not b:
b = number()
print(a,b)
for i in range(5):
func(i)
Also make sure that you use only immutables as default arguments
def append(a, values=[]):
values.append(a)
return values
append("A")
append("B")
def append(a, values=None):
if values is None:
values = []
values.append(a)
return values
append("A")
append("B")
def summation(values, *, initial=0):
return initial + sum(values)
summation(range(10), initial=50)
summation(range(10), 0)
def func(*args):
pass
func(1)
func(1,2)
func(1,2,3,4,5)
def func(*args):
print(args)
func(1,2,3,4,5)
problem: Write a function genericsum which sums up all arguments passed to it
>>> genericsum(1,1,1,1,1)
5
>>> genericsum(1,2,3)
6
",".join(["a","b"])
def joinstrings(*args, sep=" "):
alltogether = args[0]
for word in args[1:]:
alltogether = alltogether + sep + word
return alltogether
joinstrings("join","these","strings","with","space")
joinstrings(["a","b","c"],["b","c"])
fun(1,2,3,4)
def make_person(name, **kwargs):
person = {"name":name}
for key,value in kwargs.items():
person[key] = value
return person
make_person(name="haskell",surname="curry",email="haskell@functional.expressions.com")
def fun(*args):
print(args)
print(*args)
fun(1,2,3,4)
fun([1,2,3,4])
def genericsum(*args):
s = 0
for item in args:
s += item
return s
def find_stats(*args):
results = { 'sum':genericsum(*args),
'mean':genericsum(*args)/len(args),
'max':max(args),
'min':min(args)
}
return results
find_stats(0.1,0.2,0.3,0.11,0.12,0.23)
def timeseries(*values, **metadata):
stats = find_stats(*values)
ploting_data = {}
ploting_data['values'] = values
ploting_data['stats'] = stats
for key, value in metadata.items():
ploting_data[key] = value
return ploting_data
timeseries(0.01,0.001,0.011,0.013,0.089,
group = "cancer",
observations = "raw intensity",
experiment = "gene expression",
gene = "RC311")
def func(x):
return 2*x
func
print(func)
type(func)
twotimes = func
twotimes
twotimes(2)
twotimes == func
def sum_natural(n):
s = 0
for num in range(1,n+1):
s += num
return s
def square(x):
return x*x
def sum_squares(n):
s = 0
for num in range(1,n+1):
s += square(num)
return s
def cube(x):
return x*x
def sum_cubes(n):
s = 0
for num in range(1,n+1):
s += cube(num)
return s
def sum_func(n, func):
s = 0
for num in range(1,n+1):
s += func(num)
return s
sum_squares(40)
sum_func(40, square)
sqr = lambda x:x*x
sum_func(40, lambda x:x*x)
8/1*3 + 8/5*7 + 8/9*11....
this series slowly converges pi
sum_func(10000, lambda n:8/((4*n-3)*(4*n-1)))
def make_adder(x):
def adder(y):
return x+y
return adder
adder5 = make_adder(5)
adder5
type(adder5)
adder5(10)
adder5(12)
adder7 = make_adder(7)
adder7(5)
def make_logger(prefix):
def logger(*args):
print(prefix, *args)
return logger
info = make_logger("[INFO]:")
warning = make_logger("[WARNING]:")
info("Called function", square)
warning("Something went wrong!")
records = [
("A",40),
("B",86),
("C",48),
("D",75)
]
def get_score(record):
return record[1]
max(records, key=get_score)
records = [
("A",90,6.6),
("B",100,6.7),
("C",110,7.0),
("D",95, 10.0)
] ## column0 is name, column1 is systolicBP, column2 is sugar in blood
def column(index):
return lambda row:row[index]
max(records, key=column(1)) # person with highest BP
max(records, key=column(2)) # person with highest sugar
import os
words = ["one","two","three","four","five"]
max(words)
max(words, key=len)
files = os.listdir(os.getcwd())
files
max(files, key = os.path.getsize)
def compose(f, g):
return lambda x: f(g(x))
twotimes_and_square = compose(square, twotimes)
twotimes_and_square(3)
problem A number x is called fixed point of a function if x satisfies the equation f(x) = x. For some function f we locate fixed point by begining with an initial guess and applying f repeatedly, f(x), f(f(x)), f(f(f(x)))..write a python function to find fixed point of a function. it should take function as first argument, initial guess and accurracy (default= 0.0001) for equating f(x) = x
import math
fixed_point(math.cos, 1, 0.0001)
0.739054...
def fixed_point(f, guess, tollerence=0.0001):
"""
computes fixed point of a mathematical function.
x is fixed point of f if f(x) = x
"""
prev = f(guess)
current = f(prev)
while abs(prev-current) > tollerence:
prev, current = current, f(current)
return current
import math
fixed_point(math.cos, 1)
bonus problem
`
a = 1934
ma = 9431 rarrange the digits to form max number
mia = 1349 rearrange the digits to form min nmumber
a = ma - mia change a to difference of these two
make a function for above iteration. find fixed point of that function.
def add(x,y):
# print(x,y)
return x+y
def sub(x,y):
#print(x,y)
return x-y
def mult(x,y):
#print(x,y)
return x*y
def debug(f):
def wrapper(*args):
print(f.__qualname__, args)
return f(*args)
return wrapper
addnew = debug(add)
addnew(3,4)
add = debug(add)
add(5,6)
sytactic sugar for this is
@debug # equivalent to fib = debug(fib)
def fib(n):
if n in [1,2]:
return 1
else:
return fib(n-1) + fib(n-2)
fib(5)
@debug
def square(x):
return x*x
@debug
def sumofsquares(x,y):
return square(x) + square(y)
sumofsquares(3,4)
def debug(f):
def wrapper(*args, **kwargs):
print(f.__qualname__, args, kwargs)
return f(*args, **kwargs)
return wrapper
@debug
def add(x,y):
return x+y
add(3,4, name="python")
volume = debug(cylinder_volume)
volume(radius=5, height=10)
volume(5, 10)
volume(5, height=10)
%%file trace.py
import os
level = 0
def log(*args):
if os.getenv("DEBUG") == "true":
print(*args)
def trace(f):
def g(*args):
global level
log("| " * level + "|--" + f.__qualname__, args)
level += 1
value = f(*args)
level -= 1
log("| " * level + "|--" + "return", value)
return value
return g
%%file sum.py
from trace import trace
@trace
def square(x):
return x*x
@trace
def sum_of_squares(x,y):
return square(x) + square(y)
if __name__ == "__main__":
print(sum_of_squares(3,4))
!python sum.py
!DEBUG="true" python sum.py
%%file fib.py
import sys
from trace import trace
@trace
def fib(n):
if n in [1,2]:
return 1
else:
return fib(n-1) + fib(n-2)
def main():
n = int(sys.argv[1])
fib(n)
if __name__ == "__main__":
main()
!DEBUG=true python fib.py 8
problem: Write a decorator depricated that prints a warning message saying that function is deprecated everytime it is called
@depricated
def square(x):
return x*x
print(square(4))
WARNING: function square is depricated.
16
problem: Write a decorator with_retries that continues to retry the function for 5 times if there is any exception raised while calling original function
from urllib.request import urlopen
@with_retries
def wget(url):
return urlopen(url).read()
wget("http://google.com/nosuchpage/")
Failed to download, retrying...
Failed to download, retrying...
Failed to download, retrying...
Failed to download, retrying...
Failed to download, retrying...
Giving up!
def depricated(f):
def wrapper(*args):
print("WARNING: function", f.__qualname__, "is depricated.")
return f(*args)
return wrapper
@depricated
def square(x):
return x*x
square(3)
square(5)
def with_retries(f):
def wrapper(*args):
for i in range(5):
try:
return f(*args)
except Exception as e:
print(e,"retrying..")
print("Giving up!")
return wrapper
from urllib.request import urlopen
@with_retries
def wget(url):
return urlopen(url).read()
wget("http://google.com/nosuchpage")
%%file memoize.py
def memoize(func):
cache = {}
def wrapper(*args):
if args not in cache:
cache[args] = func(*args)
return cache[args]
return wrapper
from memoize import memoize
@memoize
def square(x):
print("calling is square", x)
return x*x
square(5)
square(5)
%%file fib1.py
import sys
from memoize import memoize
from trace import trace
@memoize
@trace
def fib(n):
if n in [1,2]:
return 1
else:
return fib(n-1) + fib(n-2)
def main():
n = int(sys.argv[1])
fib(n)
if __name__ == "__main__":
main()
!DEBUG=true python fib1.py 8
!!DEBUG=true python fib.py 8
problem Write a module cmdline.py to build command-line applications easily from your existing functions.
from cmdline import command, main
@command
def hello():
"""
Prints hello
"""
print("Hello World!")
@command
def cat(filename):
"""
prints given file to standard ouput
"""
print(open(filename.read())
@command
def grep(word, filename):
"""
greps given phrase in file
"""
for line in open(filename):
if word in line:
print(line.strip())
if __name__ =="__main__":
main()
$python commands.py hello
Hello World!
%%file cmdline.py
import sys
commands = {}
def command(f):
commands[f.__name__] = f
return f
def help_():
print("Available commands")
for cmd in command.keys():
print(cmd.ljust(10), commands[cmd].__doc__.strip())
def main():
cmdname = sys.argv[1]
args = sys.argv[2:]
if "help" in sys.argv:
help_()
elif cmdname in commands.keys():
f = commands[cmdname]
print("Executing command", cmdname)
f(*args)
else:
print("No command", cmdname)
%%file commands.py
from cmdline import command, main
@command
def hello():
"""
Prints hello
"""
print("Hello World!")
@command
def cat(filename):
"""
prints given file to standard ouput
"""
print(open(filename).read())
@command
def grep(word, filename):
"""
greps given phrase in file
"""
for line in open(filename):
if word in line:
print(line.strip())
if __name__ =="__main__":
main()
!python commands.py grep "hello" commands.py
!python commands.py cat data.csv
!python commands.py help
%%file module.py
def backup(file, loc):
# do some copying stuff
#delete file
print("calling backup")
pass
print(__name__)
backup("hello.txt","/tmp/")
!python module.py
import module
%%file module1.py
def backup(file, loc):
# do some copying stuff
#delete file
print("calling backup")
pass
print(__name__)
if __name__ == "__main__":
backup("hello.txt","/tmp/")
!python module1.py
import module1
@with_retries(retries=3, delay=0.1)
def wget(url):
@debug(prefix="****")
def fib(n):
@login_required(role="admin)
def edit_interface():
import time
def with_retries(retries=5, delay=0):
def decor(f):
def wrapper(*args):
print("retries=", retries, "delay=",delay)
for i in range(retries):
try:
return f(*args)
except Exception as e:
print(f.__name__, args, "failed:", e)
time.sleep(delay)
print("Giving up!")
return wrapper
return decor
from urllib.request import urlopen
@with_retries(retries=3, delay=0.5)
def wget(url):
"""
downloads given url from web
"""
response = urlopen(url)
if response:
return response.read()
wget("http://google.com/nosuchpage/")
import time
from functools import partial
def with_retries(f=None, retries=5, delay=0):
if f == None:
return partial(with_retries, retries=retries, delay=delay)
def g(*args):
print("retries=", retries, "delay=",delay)
for i in range(retries):
try:
return f(*args)
except Exception as e:
print(f.__name__, args, "failed:", e)
time.sleep(delay)
print("Giving up!")
return g
print(wget)
wget.__name__
from functools import wraps
def decorator(f):
@wraps(f)
def wrapper(*args):
print("before calling function", f.__qualname__)
result = f(*args)
print("after calling function", f.__qualname__)
return result
return wrapper
@decorator
def add(x,y):
"""
adds x and y
"""
return x+y
add(2,3)
print(add)
help(add)
help(wget)
add.__qualname__
$ sqlite3 a.db
SQLite version 3.13.0 2016-05-18 10:57:30
Enter ".help" for usage hints.
sqlite> create table person(name varchar(100), email varchar(100));
sqlite> select * person
...> ;
Error: near "person": syntax error
sqlite> select * from person;
sqlite> insert into person (name, email) values('alice','alice@example.com');
sqlite> select * from person;
alice|alice@example.com
sqlite>
import sqlite3
conn = sqlite3.connect("a.db")
cur = conn.cursor()
results = cur.execute("select * from person")
results
results.fetchall()
#bad way of doing it
def find_person(name):
q = "select * from person where name='{}'".format(name)
print(q)
cur = conn.cursor()
results = cur.execute(q)
return results.fetchone()
find_person("alice")
def find_person(email):
query = "select * from person where email=?"
cur = conn.cursor()
results = cur.execute(query, (email,))
return results.fetchone()
find_person("alice@example.com")
def query(conn, querystring, params=()):
cur = conn.cursor()
results = cur.execute(querystring, params)
return results.fetchall()
query(conn, "select * from person where name=?", ("alice",))
query(conn, "select * from person")
conn.close()
conn = sqlite3.connect("a.db")
cur = conn.cursor()
persons = [("dilbert", "dilbert@dilbert.com"),
("calvin", "calvin@calvinhobes.com"),
("jerry", "jerry@disney.com")]
cur.executemany("insert into person values(?,?)", persons)
conn.commit() # this will save changes to db file
conn.close()
conn = sqlite3.connect("a.db")
cur = conn.cursor()
for name, email in cur.execute("select * from person ORDER by name"):
print(name, email)
from sqlalchemy import Table, Column, Integer, String, MetaData, ForeignKey, create_engine
metadata = MetaData()
users = Table('users', metadata,
Column('id', Integer, primary_key=True),
Column("name", String),
Column("email", String))
posts = Table("posts", metadata,
Column('id', Integer, primary_key=True),
Column("author_id", Integer, ForeignKey('users.id')),
Column('title', String),
Column("body", String))
engine = create_engine("sqlite:///test.db", echo=True)
metadata.create_all(engine)
q = users.insert().values(name="Alice",email="alice@example.com")
metadata.bind = engine
q.execute()
results = users.select().execute()
results.fetchall()
select = users.select()
q = select.where(users.columns.email=="alice@example.com")
print(q)
print(select)
select.where(users.columns.name=="Alice").execute().fetchall()
engine = create_engine("sqlite:///test.db")
metadata = MetaData(engine)
metadata.tables
metadata.reflect() # loads all the existing table definations
metadata.tables
from sqlalchemy import Table, Column, Integer, String, MetaData, ForeignKey, create_engine
from sqlalchemy.ext.declarative import declarative_base
engine = create_engine("sqlite:///test.db")
Base = declarative_base()
# connect the engine
Base.metadata.bind = engine
class User(Base):
__tablename__ = "users"
id = Column(Integer, primary_key=True)
name = Column(String)
email = Column(String)
def __repr__(self):
return "User({0},{1})".format(self.name, self.email)
class Post(Base):
__tablename__ = "posts"
id = Column(Integer, primary_key=True)
author_id = Column(Integer, ForeignKey("users.id"))
title = Column(String)
body = Column(String)
def __repr__(self):
return "Post({author}, {title})".format(author = self.author_id, title=self.title)
from sqlalchemy.orm import sessionmaker
DBSession = sessionmaker(bind=engine)
session = DBSession()
new_user = User(name="anand", email="anand@xyz.com")
session.add(new_user)
session.commit()
q = session.query(User)
print(q.all())
q.filter(User.name=="anand").all()
q = session.query(User, Post)
print(q)
print(q.filter(User.id==Post.author_id))
print(User.id == Post.author_id)
q = session.query(Post)
q2 = q.join(User, User.id==Post.author_id)
print(q2)