Sep 25-27, 2019 Vikrant Patil
These notes are available online at http://notes.pipal.in/2020/arcesium_advanced_feb/day3.html
© Pipal Academy LLP
We will be using python 3.7 from anaconda for this training. You can download it from
%%file bank0.py
balance = 0
def get_balance():
return balance
def withdraw(amount):
global balance
balance -= amount
def deposit(amount):
global balance
balance += amount
import bank0
bank0.get_balance()
%%file bank1.py
def make_account():
return {"balance":0}
def get_balance(account):
return account['balance']
def withdraw(account, amount):
account['balance'] -= amount
def deposit(account , amount):
account['balance'] += amount
import bank1
a1 = bank1.make_account()
a2 = bank1.make_account()
bank1.deposit(a1, 10000)
bank1.withdraw(a1, 3000)
bank1.get_balance(a1)
class BankAccount:
def __init__(self, balance):
self.balance = balance
def get_balance(self):
return self.balance
def withdraw(self, amount):
self.balance -= amount
def deposit(self, amount):
self.balance += amount
b1 = BankAccount(10000)
b2 = BankAccount(0)
BankAccount
b1
isinstance(b1, BankAccount)
class Point:
def __init__(self, x, y):
self.x = x
self.y = y
p = Point(3, 5)
class Point2D:
z = 0
def __init__(self, x, y):
self.x = x
self.y = y
p2 = Point2D(5, 6)
p2.x
p2.y
p2.z
Point2D.x
Point2D.z
p21 = Point2D(2, 3)
p21.z
Point2D.z = 100
p21.z
p23 = Point2D(2,2)
p23.z
p23.__dict__
p23.z = 20
Point2D.z
p21.z
p21.__dict__
p23.__dict__
del p23.z
p23.z
p23
Question
What is the dfference when I cann hello and bar methods on an instance?
class Foo:
def hello():
pass
def bar(self):
pass
f = Foo()
f.hello()
f.bar()
Foo.hello()
f
Foo.hello
Foo.bar
f.hello
f.bar
a = [1,2]
a
class Point:
def __init__(self, x, y):
self.x = x
self.y = y
p = Point(1,2)
p
class Point:
def __init__(self, x, y):
self.x = x
self.y = y
def __repr__(self):
return "Point({},{})".format(self.x, self.y)
p = Point(2, 3)
p
print(p)
class Point:
def __init__(self, x, y):
self.x = x
self.y = y
def __repr__(self):
return "Point({},{})".format(self.x, self.y)
def __str__(self):
return "Point<{},{}>".format(self.x, self.y)
p = Point(1, 2)
p
print(p)
len([1,2,3,4])
len("2323 4232 432 4 salkdjsad fsldkj")
len({"a":1})
len({1, 2, 3})
len(p)
class Vector:
def __init__(self, x, y):
self.x = x
self.y = y
def __repr__(self):
return "Vector({},{})".format(self.x, self.y)
def __str__(self):
return "Vector<{},{}>".format(self.x, self.y)
def __len__(self):
return (self.x**2 + self.y**2)**0.5
v = Vector(1,1)
len(v)
class Vector:
def __init__(self, x, y):
self.x = x
self.y = y
def __repr__(self):
return "Vector({},{})".format(self.x, self.y)
def __str__(self):
return "Vector<{},{}>".format(self.x, self.y)
def __len__(self):
return int((self.x**2 + self.y**2)**0.5)
v = Vector(20,1)
len(v)
class Pair:
def __init__(self, x, y):
self.x = x
self.y = y
def __repr__(self):
return "Pair({},{})".format(self.x, self.y)
def __str__(self):
return "Pair<{},{}>".format(self.x, self.y)
def __len__(self):
return 2
len(Foo())
dir(1)
x = 4545454
x.__add__(2)
problem
+ -> __add__(self, c)- -> __sub__(self, c)== -> __eq__(self, c)[] -> __getitem__(self, name) and __setitem__(self, name, value)class Sealed:
def __setattr__(self, key, value):
raise Exception("No way!")
s = Sealed()
s.x = 34
class UpperCase:
def __getattr__(self, key):
return key.upper()
u = UpperCase()
u.hello
problem
class Point:
def __init__(self, x, y):
self.x = x
self.x = y
def __setattr__(self, key, value):
raise Exception("Point is immutable class, can not modify it!")
class Foo:
def __init__(self, x):
self.x = x
f = Foo(3)
f.__dict__
p = Point(4,5)
class Point:
def __init__(self, x, y):
self.__dict__['x'] = x
self.__dict__['y'] = y
def __setattr__(self, key, value):
raise Exception("Point is immutable class, can not modify it!")
class Point:
def __init__(self, x, y):
super(Point, self).__setattr__("x", x)
super(Point, self).__setattr__("y", y)
def __setattr__(self, key, value):
raise Exception("Point is immutable class, can not modify it!")
p = Point(2, 3)
p.x = 34
p.x
p.__dict__['x'] = 10
class Foo:
def __init__(self, x):
self.x = x
def doublex(self):
self.x = 2*self.x
f = Foo(3)
Foo.doublex(f)
f.x
Foo.doublex
Foo.hello = lambda x: print("Hello ", x.x)
f.hello()
Foo.hello()
class A:
pass
class B:
pass
class C(A,B):
pass
C.__mro__
class Myint:
def __init__(self, strnum):
self.value = int(strnum)
def parse(strnum):
return int(strnum)
Myint.parse("100")
int_ = Myint("23")
int_.parse("100")
class Myint:
def __init__(self, strnum):
self.value = int(strnum)
@staticmethod
def parse(strnum):
return int(strnum)
Myint.parse
a = Myint("34")
a.parse("100")
import datetime
class MyDatetime(datetime.datetime):
pass
datetime.datetime.now()
MyDatetime.now()
class A:
def instance():
return A()
class B(A):
pass
A.instance()
B.instance()
class A:
@classmethod
def instance(cls):
return cls()
class B(A):
pass
A.instance()
B.instance()
class C:
def __init__(self, x):
self.x = x
@classmethod
def instance(cls, value):
return cls(value)
class D(C):
pass
D.instance(5)
type(1)
type(A)
type(Foo)
type(MyDatetime)
class Meta(type):
pass
class SubMetaclass(Meta):
pass
SubMetaclass()
class SubMetaClass(metaclass=Meta):
pass
SubMetaClass()
type(SubMetaClass)
class Singleton(type):
def __init__(self, *args, **kwargs):
print(args)
print(kwargs)
self._instance = None
def __call__(self, *args, **kwargs):
print("__call__", self,args,kwargs)
if self._instance:
return self._instance
else:
self._instance = super().__call__(*args, **kwargs)
return self._instance
class SingletonBase(metaclass=Singleton):
pass
class X(SingletonBase):
def __init__(self, x, y):
self.x = x
self.y = y
pass
x1 = X(2,3)
del X
x2 = X()
x2
x1 is x2
class Test:
def __call__(self, *args, **kwargs):
print(*args, **kwargs)
Test()(2323,2323)
def debug(func):
prefix = "*"*10
msg = prefix + func.__qualname__
def wrapper(*args, **kwargs):
print(msg)
return func(*args, **kwargs)
return wrapper
def debugmethod(cls):
for name, val in vars(cls).items():
if callable(val):
setattr(cls, name, debug(val))
return cls
@debugmethod
class Foo:
x = "xyz"
def method1(self):
pass
def method2(self):
pass
def method2(self):
pass
f = Foo()
f.method1()
def singlton(cls):
instance = None
def wrapper(*args, **kwargs):
nonlocal instance
if instance == None:
instance = cls(*args, **kwargs)
return instance
return wrapper
@singlton
class A:
pass
@singlton
class B:
pass
a1 = A()
a2 = A()
class Integer:
def __init__(self, name):
self.name = name
def __get__(self, instance, cls):
print("__get__ from ", self)
if instance is None:
return self
else:
return instance.__dict__[self.name]
def __set__(self, instance, value):
print("__set__ from", self)
if not isinstance(value, int):
raise TypeError("Expected int")
instance.__dict__[self.name] = value
def __delete__(self, instance):
print("__del__ from", self)
del instance.__dict__[self.name]
def __str__(self):
return "Integer<0.name!s>".format(self)
class Point:
x = Integer('x')
y = Integer('y')
def __init__(self, x, y):
self.x = x
self.y = y
def __setattr__(self, name, value):
print("__setattr__ of Point")
super().__setattr__(name, value)
p = Point(2, 3)
p.x
p.y
p.x = 10
del p.x
class Person:
def __init__(self, name):
self.name = name
@property
def email(self):
return "@".join([self.name,"arcesium.com"])
@email.setter
def email(self):
raise Execption("You can't modify email!")
p = Person("Praveen")
p.email
p.email()
class my_property:
def __init__(self, func):
self.func = func
def __get__(self, instance, cls):
if instance is None:
return self
print("my_property.__get__")
return self.func(instance)
class Person:
def __init__(self, name):
self.name = name
@my_property
def email(self):
return "@".join([self.name, "gmail.com"])
p = Person("vikrant")
p.email
with open("data.csv") as f:
f.read()
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
class ContextTimer(Timer):
def reset(self):
self._start = 0
self._end = 0
def __enter__(self):
print("Begining with block")
self.reset()
self.start()
return self
def __exit__(self, exc_type, exc_value, traceback):
self.stop()
print(exc_type, exc_value, traceback)
print("Time taken in with block: ", self.get_time_taken())
with ContextTimer() as t:
print("Inside with body!")
for i in range(10000):
for j in range(10000):
s = i*j*1.0
print("End of with body")
import threading
def tick(n):
for i in range(n):
print("Tick-", i)
time.sleep(1)
def reversetick(n):
for i in reversed(range(n)):
print("Tick-down-", i)
time.sleep(1)
t1 = threading.Thread(target=tick, args=(10,))
t2 = threading.Thread(target=reversetick, args=(10,))
t1.start()
t2.start()
t1.join()
t2.join()
print("Task ..over")
event = threading.Event()
def tick(event):
i = 0
while not event.isSet():
print("Tick-", i)
time.sleep(2)
i +=1
t = threading.Thread(target=tick, args=(event,))
t.start()
event.set()
import random
def producer(data, lock, event):
while not event.isSet():
with lock:
data.append(random.choice([0,1]))
print("Produced...", data[-1])
time.sleep(1)
def consumer(data, lock, event):
while not event.isSet():
with lock:
print("Consumed ...", data.pop())
time.sleep(1)
def observer(data, lock, event):
while not event.isSet():
print(data)
time.sleep(1)
data = [1,1,2,3,4]
lock = threading.Lock()
event = threading.Event()
p = threading.Thread(target=producer, args=(data, lock, event))
c = threading.Thread(target=consumer, args=(data, lock, event))
o = threading.Thread(target=observer, args=(data, lock, event))
p.start()
c.start()
o.start()
time.sleep(3)
event.set()
from multiprocessing.pool import ThreadPool
pool = ThreadPool(4)
import requests
def download(url):
resp = requests.get(url)
return resp
def threaded_download(n):
pool = ThreadPool(n)
url = "https://ia802902.us.archive.org/4/items/prideandprejudic01342gut/pandp12.txt"
urls = [url]*10
res = pool.map(download, urls)
return res
for i in range(1,9):
with ContextTimer() as t:
threaded_download(i)
class ContextTimer(Timer):
def reset(self):
self._start = 0
self._end = 0
def __enter__(self):
self.reset()
self.start()
return self
def __exit__(self, exc_type, exc_value, traceback):
self.stop()
print("Time taken in with block: ", self.get_time_taken())
from multiprocessing.pool import Pool
def saxpy(n):
s = 0
for i in range(n):
for j in range(n//10):
s += j*i*1.0
return s
def process_pool(n):
pool = Pool(n)
args = [10000]*10
res = pool.map(saxpy, args)
return res
for i in range(1, 9):
with ContextTimer() as t:
process_pool(i)
import pandas as pd
area = pd.Series(["North", "East", "West", "South", "Central"])
area
sales = pd.Series([2,25,15,20,10], index=area)
sales
sales['North']
sales[0]
area
area[0]
area[4]
area[area=="Central"]
sales
sales.reindex(index=sorted(area))
sales
reordred = sales.reindex(index=sorted(area))
reordred
sales.mean()
sales.std()
sales[sales>10]
df = pd.DataFrame({"sales":[20,23,12,6,25],
"profit":[5,2,7,1,8]
}, index=["North", "East", "West", "South", "Central"]
)
df
df['sales']
df.sales
df.head()
weather = pd.read_csv("HYDERABAD-weather.csv")
weather.info()
weather.isnull().sum()
weather.head()
weather.tail()
df
df.loc['East']
df['sales']
df.loc['East']['profit']
df.iloc[3]
weather.groupby("month").mean()
(weather.groupby("month")
.mean()
.plot
.line(y=["maxtemp"]))
%matplotlib inline
(weather.groupby("month")
.mean()
.plot
.line(y=["maxtemp","mintemp","rainfall"]))
(weather.groupby("month")
.mean()
.plot
.bar(y=["maxtemp","mintemp","rainfall"]))
pd.read_sql_table?
help(pd.read_sql)
groupbymonth = weather.groupby("month").max()
groupbymonth
groupbymonth.describe()
%load_ext Cython
%%cython --annotate
def square(x):
return x*x
def sumofsquares(x,y):
return square(x) + square(y)
%%timeit
sumofsquares(7, 10)
def square(x):
return x*x
def sumofsquares(x,y):
return square(x) + square(y)
%%timeit
sumofsquares(7,10)
%%file cfib.pyx
from __future__ import print_function
def fib(n):
cdef int cur, prev
cur, prev = 1,1
while cur < n:
cur, prev = cur+prev, cur
print(cur, end=",")
%%file setup.py
from distutils.core import setup
from Cython.Build import cythonize
setup(ext_modules=cythonize("cfib.pyx"))
!python setup.py build_ext --inplace
!ls
import cfib
cfib.fib(1000)
%%file simple.c
int add(int x, int y){
return(x+y);
}
!gcc -c simple.c
!gcc -shared -o libsimple.so simple.o
!ls
import ctypes
import os
_file = "libsimple.so"
_path = os.path.join(os.getcwd(), _file)
_module = ctypes.cdll.LoadLibrary(_path)
add = _module.add
add.argtypes = [ctypes.c_int, ctypes.c_int]
add.restype = ctypes.c_int
add(8,10)
from numba import jit
@jit
def add(x, y):
return x+y
@jit(nogil=True)
def saxpy(n):
s = 0
for i in range(n):
for j in range(n):
s += i*j*1.0
return s
def saxpy_(n):
s = 0
for i in range(n):
for j in range(n):
s += i*j*1.0
return s
%%timeit
saxpy_(1000)
%%timeit
saxpy(1000)