Feb 13-17, 2023 Vikrant Patil
All notes are available online at https://notes.pipal.in/2023/arcesium_finop_jan/
Please login to https://engage.pipal.in/ and launch jupyter lab
For today create a notebook with name module2-day3
notebook names are case sensitive. Make sure you give correct name
© Pipal Academy LLP
tables that generates multiplication tables from 1 to 10 and writes it in csv file.>>> tables("tables.csv")
>>> print_contents("table.csv")
1,2,3,4,5,6,7,8,9,10
2,4,6,....
def generate_table(x):
return [x*i for i in range(1, 11)]
def generate_tables(n):
return [generate_table(i) for i in range(1, n+1)]
generate_table(2)
[2, 4, 6, 8, 10, 12, 14, 16, 18, 20]
generate_table(11)
[11, 22, 33, 44, 55, 66, 77, 88, 99, 110]
generate_tables(5)
[[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]]
def generate_tables(n):
tables = []
for i in range(1, n+1):# numbers for which we want to generate tables
t = []
for m in range(1, 11):
t.append(i*m)
tables.append(t)
return tables
generate_tables(6)
[[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], [6, 12, 18, 24, 30, 36, 42, 48, 54, 60]]
def writecsv(data2d, filename):
with open(filename, "w") as f:
for row in data2d:
line = ",".join([str(item) for item in row])
f.write(line)
f.write("\n")
writecsv(generate_tables(5), "tables5.csv")
!python cat.py tables5.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
t6 = generate_tables(6)
t6
[[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], [6, 12, 18, 24, 30, 36, 42, 48, 54, 60]]
t6[0]
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
strdata = []
for item in t6[0]:
strdata.append(str(item))
strdata
['1', '2', '3', '4', '5', '6', '7', '8', '9', '10']
",".join(strdata)
'1,2,3,4,5,6,7,8,9,10'
strdata = []
for item in t6[0]:
strdata.append(str(item))
def writecsv(data2d, filename):
with open(filename, "w") as f:
for row in data2d:
line = ",".join([str(item) for item in row])
f.write(line)
f.write("\n")
writecsv(t6, "tables6.csv")
!python cat.py tables6.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 6,12,18,24,30,36,42,48,54,60
def writecsv(data2d, headers, filename):
with open(filename, "w") as f:
headerline = ",".join(headers)
f.write(headerline)
f.write("\n")
for row in data2d:
line = ",".join([str(item) for item in row])
f.write(line)
f.write("\n")
writecsv(t6, list("ABCDEFGHIJ"), "tables6.csv")
def tables(n, filename):
t = generate_tables(n)
headers = [f"multiflier-{i}" for i in range(1, 11)]
writecsv(t, headers,filename)
tables(8, "tables8.csv")
Write a program center_align.py to center align all lines in the given file.
$ cat poem.txt
There was an Old Man with a beard
Who said, "It is just as I feared!
Two Owls and a Hen,
Four Larks and a Wren,
Have all built their nests in my beard!"
$ python center_align.py poem.txt
There was an Old Man with a beard
Who said, "It is just as I feared!
Two Owls and a Hen,
Four Larks and a Wren,
Have all built their nests in my beard!"
%%file center_align.py
import typer
app = typer.Typer()
@app.command()
def center_align(filename:str):
with open(filename) as f:
maxlen = 0
for line in f:
if len(line) > maxlen:
maxlen = len(line)
with open(filename) as f:
for line in f:
print(line.center(maxlen), end="")
if __name__ == "__main__":
app()
Overwriting center_align.py
"text data which is not aligned to center".center(40)
'text data which is not aligned to center'
!python center_align.py --help
Usage: center_align.py [OPTIONS] FILENAME
Arguments:
FILENAME [required]
Options:
--install-completion [bash|zsh|fish|powershell|pwsh]
Install completion for the specified shell.
--show-completion [bash|zsh|fish|powershell|pwsh]
Show completion for the specified shell, to
copy it or customize the installation.
--help Show this message and exit.
!python center_align.py poem.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!
%%file center_align1.py
import typer
app = typer.Typer()
@app.command()
def center_align(filename:str):
with open(filename) as f:
maxlen = 0
for line in f:
if len(line) > maxlen:
maxlen = len(line)
with open(filename) as f:
for line in f:
print(line.strip().center(maxlen))
if __name__ == "__main__":
app()
Writing center_align1.py
!python center_align1.py poem.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!
%%file center_align2.py
import typer
app = typer.Typer()
@app.command()
def center_align(filename:str):
with open(filename) as f:
maxlen = 0
for line in f:
if len(line) > maxlen:
maxlen = len(line)-1
with open(filename) as f:
for line in f:
print(line.strip().center(maxlen))
if __name__ == "__main__":
app()
Writing center_align2.py
!python center_align2.py poem.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!
x = "fsdfsdfdsfdsf sdsad dsadsa \n"
x.center(100)
' fsdfsdfdsfdsf sdsad dsadsa \n '
print(x.center(100))
fsdfsdfdsfdsf sdsad dsadsa
%%file center_align3.py
import typer
app = typer.Typer()
@app.command()
def center_align(filename:str):
with open(filename) as f:
longest_line = max(f, key=len)
maxlen = len(longest_line) - 1
with open(filename) as f:
for line in f:
print(line.strip().center(maxlen))
if __name__ == "__main__":
app()
Writing center_align3.py
!python center_align3.py poem.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!
object_list = [1, 2, 3, 4, 5, 6, 7, 8]
object_list.index(2) # method to access data
1
object_list.append(0) # method to manipulate data
%%file bank0.py
balance = 0
# methods
def withdraw(amount):
global balance # this tells this function that treat balance as global variable, don't create local
balance = balance - amount
def deposit(amount):
global balance
balance = balance + amount
def get_balance(amount):
return balance # there is no need of declaring balance as global
# because if any variable is not defined locally, it automatically reads global variable
Writing bank0.py
import bank0
bank0.deposit(5000)
bank0.get_balance()
--------------------------------------------------------------------------- TypeError Traceback (most recent call last) Cell In[68], line 1 ----> 1 bank0.get_balance() TypeError: get_balance() missing 1 required positional argument: 'amount'
%%file bank1.py
balance = 0
# methods
def withdraw(amount):
global balance # this tells this function that treat balance as global variable, don't create local
balance = balance - amount
def deposit(amount):
global balance
balance = balance + amount
def get_balance():
return balance # there is no need of declaring balance as global
# because if any variable is not defined locally, it automatically reads global variable
Overwriting bank1.py
import bank1
bank1.get_balance()
0
bank1.deposit(5000)
bank1.get_balance()
5000
bank1.withdraw(3000)
bank1.get_balance()
2000
%%file bank2.py
def make_account(balance):
account = {"balance":balance}
return account
# methods
def withdraw(account, amount):
account['balance'] -= amount
def deposit(account, amount):
account['balance'] += amount
def get_balance(account):
return account['balance']
Writing bank2.py
import bank2
acc1 = bank2.make_account(500)
acc2 = bank2.make_account(5000)
bank2.get_balance(acc1)
500
bank2.deposit(acc1, 3000)
bank2.get_balance(acc1)
3500
bank2.get_balance(acc2)
5000
bank2.withdraw(acc2, 300)
bank2.get_balance(acc2)
4700
bank2.get_balance(acc1)
3500
class BankAccount:
def __init__(self):
self.balance = 0
def get_balance(self):
return self.balance
def deposit(self, amount):
self.balance += amount
def withdraw(self, amount):
self.balance -= amount
A1 = BankAccount() #__init__ has only self argument
A1.get_balance() # you don't pass self
0
A1.deposit(5000)
A1.get_balance()
5000
class BankAccount1:
def __init__(self, balance):
self.balance = balance
def get_balance(self):
return self.balance
def deposit(self, amount):
self.balance += amount
def withdraw(self, amount):
self.balance -= amount
A_ = BankAccount1()
--------------------------------------------------------------------------- TypeError Traceback (most recent call last) Cell In[99], line 1 ----> 1 A_ = BankAccount1() TypeError: BankAccount1.__init__() missing 1 required positional argument: 'balance'
A_ = BankAccount1(4000)
A_.get_balance()
4000
a = BankAccount1(3000)
b = BankAccount1(5000)
c = BankAccount1(7000)
type(a)
__main__.BankAccount1
type([1 , 2, 3, 4])
list
isinstance(1, int)
True
isinstance("1", int)
False
isinstance(a, BankAccount1)
True
isinstance(a, BankAccount)
False
0
0
def add():
pass
add
<function __main__.add()>
type(add)
function
with open("poem.txt") as f:
print(type(f))
<class '_io.TextIOWrapper'>
class BankAccount:
def __init__(self, balance): # constructor
self.minimum_balance = 1000
if balance < self.minimum_balance:
raise Exception(f"To start this account, you need to have minimum {self.minimum_balance} balance")
self.balance = balance
def get_balance(self):
return self.balance
def deposit(self, amount):
self.balance += amount
def withdraw(self, amount):
if self.balance - amount <= self.minimum_balance:
raise Exception(f"You can withdraw , beacuase your balance can not be below {self.minimum_balance}")
self.balance -= amount
class ZeroBalanceAccount(BankAccount):
def __init__(self):
self.balance = 0
def withdraw(self, amount):
self.balance -= amount
b1 = BankAccount(500)
--------------------------------------------------------------------------- Exception Traceback (most recent call last) Cell In[120], line 1 ----> 1 b1 = BankAccount(500) Cell In[119], line 6, in BankAccount.__init__(self, balance) 4 self.minimum_balance = 1000 5 if balance < self.minimum_balance: ----> 6 raise Exception(f"To start this account, you need to have minimum {self.minimum_balance} balance") 7 self.balance = balance Exception: To start this account, you need to have minimum 1000 balance
z1 = ZeroBalanceAccount()
z1.get_balance()
0
b1 = BankAccount(1500)
b1.withdraw(700)
--------------------------------------------------------------------------- Exception Traceback (most recent call last) Cell In[124], line 1 ----> 1 b1.withdraw(700) Cell In[119], line 18, in BankAccount.withdraw(self, amount) 16 def withdraw(self, amount): 17 if self.balance - amount <= self.minimum_balance: ---> 18 raise Exception(f"You can withdraw , beacuase your balance can not be below {self.minimum_balance}") 19 self.balance -= amount Exception: You can withdraw , beacuase your balance can not be below 1000
z1.deposit(1000)
z1.withdraw(400)
z1.get_balance()
600
isinstance(z1, ZeroBalanceAccount)
True
isinstance(z1, BankAccount)
True
class Foo:
pass
f = Foo()
type(f)
__main__.Foo
problem
Light Light
+---------------+
| |<---------switch_on
| on=True |
| |<---------switch_off
+---------------+
|
|
+------<------- is_on
BankAccount
__main__.BankAccount
BankAccount.deposit(500) # it took 500 as self!
--------------------------------------------------------------------------- TypeError Traceback (most recent call last) Cell In[137], line 1 ----> 1 BankAccount.deposit(500) # it took 500 as self! TypeError: BankAccount.deposit() missing 1 required positional argument: 'amount'
acc = BankAccount(6000)
acc.deposit(500) # instance.deosite... self will be passed by python,, 500 is passed as amount
acc.get_balance()
6500
BankAccount
__main__.BankAccount
acc
<__main__.BankAccount at 0x7f5dab759750>
type(BankAccount) # its a class
type
type(acc)
__main__.BankAccount
acc.get_balance()
6500
class FooBar:
def method(): # no self is given!
print("hello")
fb = FooBar()
fb.method() # self will be passed automatically
--------------------------------------------------------------------------- TypeError Traceback (most recent call last) Cell In[150], line 1 ----> 1 fb.method() TypeError: FooBar.method() takes 0 positional arguments but 1 was given
class Light:
def __init__(self):
self.state = False
def is_on(self):
return self.state == True
def switch_off(self):
if self.state: # if it is on
self.state = False
def switch_on(self):
if not self.state: #if it is off
self.state = True
def toggle(self):
pass # above check is required only if we have some method like this
l = Light()
l.is_on()
False
l.switch_on()
l.is_on()
True
all_lights_in_house = [Light(), Light(), Light(), Light()]
def switch_on_all(lights):
for l in lights:
l.switch_on()
all_lights_in_house
[<__main__.Light at 0x7f5dab710bb0>, <__main__.Light at 0x7f5dab713d00>, <__main__.Light at 0x7f5dab712b90>, <__main__.Light at 0x7f5dab713610>]
def print_status(lights):
for l in lights:
print(l.is_on())
print_status(all_lights_in_house)
False False False False
switch_on_all(all_lights_in_house)
print_status(all_lights_in_house)
True True True True