Nov 20-22, 2017 Vikrant Patil
These notes will be available online at http://notes.pipal.in/2017/vmware-nov-advpython/ after this training!
© Pipal Academy LLP
def f(x):
print(x)
return 2*x
f(2)
x
amount = 10000
balance = 50000
def withdraw(balance, amount):
balance = balance - amount
return balance
fixdep = withdraw(balance, amount)
print("balance ", balance)
print("amount ",amount)
hello = "Hello initial"
def firstlevel():
hello = "Hello inside first level"
def secondlevel1():
hello = "Hello inside secondlevel1"
def secondlevel2():
nonlocal hello
hello = "hello from secondlevel2"
def thirdlevel():
global hello
hello = "from thirdlevel"
thirdlevel()
print(hello)
secondlevel1()
secondlevel2()
firstlevel()
print("*"*5, hello)
What will be output of this?
def f(x):
x.append(5)
def g(x):
x = [1,1,1,1,1]
l = [1,2,3,4]
f(l)
print(l)
g(l)
print(l)
def f(x):
x.append(5)
def g(x):
x = [1,1,1,1,1]
l = [1,2,3,4]
f(l)
l
g(l)
l
systactically class looks like this
class ClassName:
<statement>
<statement>
.
.
.
import math
class Circle:
def __init__(self, radius):
self.radius = radius
def area(self):
return math.pi * self.radius**2
class Square:
def __init__(self, side):
self.side = side
def area(self):
return self.side**2
class Triangle:
def __init__(self, base, height):
self.base = base
self.height = height
c = Circle(1.0)
s = Square(1.0)
t = Triangle(1, 1)
c.area()
shapes = [Circle(1.0), Circle(2.0), Square(1.0), Square(2.0)]
areas = [s.area() for s in shapes]
shapes.append(Triangle(1, 1))
shapes
print(areas)
areas = [s.area() for s in shapes]
%%file bank0.py
balance = 0
def deposite(amount):
global balance
balance = balance + amount
def withdraw(amount):
global balance
balance = balance - amount
def get_balance():
return balance
def main():
print(get_balance())
deposite(100)
print(get_balance())
withdraw(20)
print(get_balance())
if __name__ == "__main__":
main()
!python bank0.py
%%file bank1.py
def make_account():
return {"balance":0}
def deposite(account, amount):
account['balance'] += amount
def withdraw(account, amount):
account['balance'] -= amount
def get_balance(account):
return account['balance']
def main():
a1 = make_account()
a2 = make_account()
print("a1:",get_balance(a1))
deposite(a1, 100)
print("a1:",get_balance(a1))
deposite(a2, 200)
withdraw(a2, 20)
print("a2:",get_balance(a2))
if __name__ == "__main__":
main()
!python bank1.py
%%file bank2.py
"""
class based implementation of bank account
"""
class BankAccount:
def __init__(self):
self._balance = 0
def deposite(self, amount):
self._balance += amount
def withdraw(self, amount):
self._balance -= amount
def get_balance(self):
return self._balance
def main():
a1 = BankAccount()
a2 = BankAccount()
a1.deposite(100)
a2.deposite(200)
print("a1: {balance1}, a2: {balance2}".format(balance1=a1.get_balance(),
balance2=a2.get_balance()))
a1.withdraw(20)
a2.withdraw(30)
print("a1: {balance1}, a2: {balance2}".format(balance1=a1.get_balance(),
balance2=a2.get_balance()))
if __name__ == "__main__":
main()
!python bank2.py
class Formatter:
def format_text(self, text):
"""
Formats given text
This implementation returns same text.
subclasses should override this method
to change formatig
"""
return text
def format_file(self, name):
text = open(name).read()
return self.format_text(text)
class UpperCaseFormnatter(Formatter):
def format_text(self, text):
return text.upper()
f = UpperCaseFormnatter()
f.format_text("hello")
%%file five.txt
one
two
three
four
five
print(f.format_file("five.txt"))
class LineFormatter(Formatter):
def format_line(self, line):
return line
def format_text(self, text):
lines = text.split("\n")
lines = [self.format_line(l) for l in lines]
return "\n".join(lines)
class PrefixFormatter(LineFormatter):
def __init__(self, prefix):
self.prefix = prefix
def format_line(self, line):
return self.prefix + line
f = PrefixFormatter("[Info]")
print(f.format_text("hello\nworld"))
print(f.format_file("five.txt"))
class ClassA:
value = 42
def f(self):
return ("Hello from ClassA")
ClassA
ClassA.value
ClassA.f
a = ClassA()
a.__class__
a.value
a.f
a.f()
ClassA.f()
ClassA.f(a)
a.my_own_value = 43
a.my_own_value
ClassA.my_own_value
ClassA.y = 3
a.y
ClassA.y
b = ClassA()
b.y
del ClassA.y
b.y
class A:
x = 0
def __init__(self, v):
self.y = v
a = A(2)
A.y
a.y
a.x
a1 = A(3)
a2 = A(4)
a1.x
a2.x
A.x = 42
a.x
a1.x
a2.x
a1.x = 43
a2.x
x = ClassA()
method = x.f
method()
ClassA.f2 = lambda self, y: self.value+y
d = ClassA()
d.f2(4)
a2.new1 = 32
a2.__dict__
a1.__dict__
a.__dict__
a.x
s = "one\ntwo"
s
print(s)
class Pair(object):
def __init__(self, x, y):
self.x = x
self.y = y
def __repr__(self):
return 'Pair({0.x!r},{0.y!r})'.format(self)
def __str__(self):
return '({0.x!s},{0.y!s})'.format(self)
p = Pair(2,3)
p
print(p)
repr([1,2])
str([1,2])
class Pair(object):
def __init__(self, x, y):
self.x = x
self.y = y
def __repr__(self):
return 'Pair({0.x!r},{0.y!r})'.format(self)
def __str__(self):
return '({0.x!s},{0.y!s})'.format(self)
def __add__(self, p):
return Pair(self.x+p.x, self.y+p.y)
def __sub__(self, p):
if isinstance(p, int):
return Pair(self.x-p, self.y-p)
else:
return Pair(self.x -p.x, self.y-p.y)
def __rmul__(self, c):
return Pair(self.x*c, self.y*c)
def __mul__(self, c):
return self.__rmul__(c)
def __eq__(self,p):
return self.x==p.x and self.y==p.y
p1 = Pair(2,3)
p2 = Pair(1,4)
p1+p2
p1-p2
p1-3
p1 == p2
p1 == p1
class Pair(object):
def __init__(self, x, y):
self.x = x
self.y = y
def __repr__(self):
return 'Pair({0.x!r},{0.y!r})'.format(self)
def __str__(self):
return '({0.x!s},{0.y!s})'.format(self)
def __getitem__(self, name):
if name == "x":
return self.x
elif name == "y":
return self.y
def __setitem__(self, name, value):
if name in ["x","y"]:
self.__dict__[name] = value
else:
raise Exception("Only x,y values can be set")
p = Pair(2,3)
x = 2
p['x']
p['y']
p['x']
p.x
class UpperCase:
def __getattr__(self, name):
return name.upper()
u = UpperCase()
u.hello
u.python
class Sealed:
def __setattr__(self, name, value):
raise Exception("No chance!")
s = Sealed()
s.x = 3
class Date:
__slots__ = ['year','month','day']
def __init__(self, year, month, day):
self.year = year
self.month = month
self.day = day
d = Date(2017,11,22)
d.x
d.y = 3
class Base:
def __init__(self):
print("Base.__init__")
class A(Base):
def __init__(self):
Base.__init__(self)
print("A.__init__")
class B(Base):
def __init__(self):
Base.__init__(self)
print("B.__init__")
class C(A,B):
def __init__(self):
A.__init__(self)
B.__init__(self)
print("C.__init__")
c = C()
class Base:
def __init__(self):
print("Base.__init__")
class A(Base):
def __init__(self):
super().__init__()
#Base.__init__(self)
print("A.__init__")
class B(Base):
def __init__(self):
#Base.__init__(self)
super().__init__()
self.value = 0
print("B.__init__")
class C(B,A):
def __init__(self):
#A.__init__(self)
#B.__init__(self)
super().__init__()
print("C.__init__")
c = C()
C.__mro__
c.value
problem Write a class Timer to measure time taken in a task. The class should have start and stop methods to start and stop timer. use time.time() to get timestamp at given instant. your class should work as given below
t = Timer()
t.start()
time.sleep(5)
t.stop()
print("Time taken:",t.get_time_taken())
import time
class Timer:
def start(self):
self.starttime = time.time()
def stop(self):
self.endtime = time.time()
def get_time_taken(self):
return self.endtime - self.starttime
t = Timer()
t.start()
for i in range(10000000):
i*i*i
t.stop()
print("Time taken:", t.get_time_taken())
with open("five.txt", "w") as f:
f.write("six\n")
f.write("seven\n")
from socket import socket, AF_INET, SOCK_STREAM
class LazyConnection:
def __init__(self, address, family=AF_INET, type_=SOCK_STREAM):
self.address = address
self.family = family
self.type_ = type_
self.sock = None
def __enter__(self):
print("Inside enter...")
if self.sock is not None:
raise RuntimeError("Socket already opened!")
self.sock = socket(self.family, self.type_)
self.sock.connect(self.address)
return self.sock
def __exit__(self, exeptn_type, exceptn_value, traceback):
print("Inside exit...", exeptn_type, exceptn_value, traceback)
self.sock.close()
self.sock = None
from functools import partial
conn = LazyConnection(("www.python.org", 80))
with conn as s:
s.send(b'GET /index.html HTTP/1.0\r\n')
s.send(b'Host: www.python.org\r\n')
s.send(b'\r\n')
resp = b''.join(iter(partial(s.recv, 8192), b''))
print(resp.decode("utf-8"))
problem Write a class ContextTimer which extends from our original class Timer. This new class should implement context management protocol. When you enter the with block timer should start. and when you exit with block timer should stop and print value of time taken for executing with block
with ContextTimer() as ct:
for i in range(10000):
for j in range(1000):
s = 1*j*1.0
Time taken in with block: 2.12...
class Person:
def __init__(self, name):
self._name = name
def email(self):
return self._name + "@vmware.com"
p = Person("alice")
p.email()
class Person:
def __init__(self, name):
self._name = name
@property
def email(self):
return self._name + "@vmware.com"
@email.setter
def email(self, value):
raise Exception("Email can not be set")
@email.deleter
def email(self):
raise Exception("Email can not be deleted")
p = Person("alice")
p.email
p.email= "alice@example.com"
p.email()
class Email:
def __init__(self, name, domain):
self.name = name
self.domain = domain
def email(self):
return self.name + "@" + self.domain
def __str__(self):
return self.email()
def __repr__(self):
return "Email({0.name!r},vmware.com)".format(self)
class Person:
def __init__(self, name):
self._name = name
@property
def email(self):
return Email(self._name, "vmware.com")
@email.setter
def email(self, value):
raise Exception("Email can not be set")
@email.deleter
def email(self):
raise Exception("Email can not be deleted")
p = Person("alice")
p.email
print(p.email)
str(p.email)
del p.email
p.email = Email("hello", "somedomain.com")
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("__delete__ from", self)
del instance.__dict__[self.name]
def __str__(self):
return "Integer<{0.name!s}>".format(self)
def __repr__(self):
return "Integer({0.name!r})".format(self)
class Point:
x = Integer("x")
y = Integer("y")
def __init__(self, x, y):
self.x = x
self.y = y
p = Point(2,3)
p.x
p.x = 3
Lets implement my_property using descriptor
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, email):
self._name = name
self._email = email
@my_property
def name(self):
return self._name
p = Person("alice", "alice@example.com")
p.name
from datetime import datetime
class MyDatetime(datetime):
pass
datetime.now()
MyDatetime.now()
class A:
def __init__(self, x):
self.x = x
def __repr__(self):
return "{0}({1})".format(self.__class__.__name__, repr(self.x))
@staticmethod
def parse1(value):
return A(int(value))
@classmethod
def parse2(cls, value):
return cls(value)
class B(A):
pass
a = A.parse1("123")
a
b = B.parse1("123")
b
c = B.parse2("123")
c
%%file threads.py
import threading
import sys, time
def countdown():
for i in reversed(range(10)):
time.sleep(0.25)
print("Finished: ", threading.currentThread().getName())
def main():
n = int(sys.argv[1])
threads = [threading.Thread(target=countdown) for i in range(n)]
for t in threads:
t.start()
for t in threads:
t.join()
if __name__ == "__main__":
main()
!time -p python threads.py 10
!seq 10 | xargs printf "http://httpbin.org/get?x=%d\n" >> urls.txt
%%file sget.py
import sys
from urllib.request import urlopen
def get_urls(filename):
return [line.strip() for line in open(filename)]
def wget(url):
return urlopen(url).read()
def main():
filename = sys.argv[1]
for url in get_urls(filename):
wget(url)
if __name__ == "__main__":
main()
!time -p python sget.py urls.txt
%%file pget.py
import sys
from sget import get_urls, wget
from multiprocessing.pool import ThreadPool
def main():
filename = sys.argv[1]
concurrency = int(sys.argv[2])
urls = get_urls(filename)
pool = ThreadPool(concurrency)
pool.map(wget, urls)
if __name__ == "__main__":
main()
!time -p python pget.py urls.txt 2
!time -p python pget.py urls.txt 4
%%file pcpu.py
import sys
from multiprocessing.pool import Pool
def task(dummy):
s = 0
for i in range(10000):
for j in range(1000):
s = s+i*j*1.0
return s
def main():
conc = int(sys.argv[1])
pool = Pool(conc)
pool.map(task, range(10))
if __name__ == "__main__":
main()
!time -p python pcpu.py 1
!time -p python pcpu.py 2
!time -p python pcpu.py 4
from threading import Event, Thread
def task(n , event):
while (not event.is_set()) and n>0:
print("T-minus", n)
n -= 1
time.sleep(5)
print("Stopping, Bye!")
e = Event()
t = Thread(target=task, args=(10, e))
t.start()
e.set()
google for