records = [("HCL", 23.5, 123),
("INFY", 12.5, 500.5)]Module 2 - Day 3
Classes and OOPS
record = {"name":"HCL",
"gain": 23.5,
"price": 123}record # named collection of data{'name': 'HCL', 'gain': 23.5, 'price': 123}
r = records[0] # non named collection of data
r('HCL', 23.5, 123)
record['name']'HCL'
r[0] # name is in programmer's head! it is assumption that first entry is name... second is gain and third entry is price'HCL'
Data encapsulation can be represented as
Instance of class
+---------------+
| |<---------methods to manipulate data
| data |
| |<---------methods
+---------------+
|
|
+------<------- methods to access data
Example Bank Account
What all is needed to create bank account
- Identification and proof of indentification
- balance (central requirement)!
- salary/current/savings/FD/PPF
%%file bank0.py
balance = 0
def deposite(amount):
global balance # this global statement tells that , don't treat balance as local variable
balance = balance + amount
def withdraw(amount):
global balance
balance = balance - amount
def get_balance():
return balance # if there is no local variable automatically global variable is accessed for reading
Writing bank0.py
import bank0 # we import our bank modulebank0.get_balance()0
bank0.deposite(5000)bank0.get_balance()5000
bank0.withdraw(1000)bank0.get_balance()4000
import bank0 # reimporting a module is not possible. python allows importing it only once. this statement has no effectbank0.get_balance()4000
%%file bank1.py
def create_account(name, balance):
return {"name": name,
"balance": balance}
def deposite(account, amount):
#account['balance'] = account['balance'] + amount
account['balance'] += amount # += operator says add whatever is on right to whatever is on left
def withdraw(account, amount):
account['balance'] -= amount
def get_balance(account):
return account['balance']Overwriting bank1.py
import bank1a1 = bank1.create_account("Vikrant", 5000)
a2 = bank1.create_account("Vishal", 4000)bank1.get_balance(a1)5000
bank1.get_balance(a2)4000
bank1.deposite(a1, 10000)bank1.get_balance(a1)15000
bank1.get_balance(a2)4000
a3 = bank1.create_account("Arcesium", 10000)bank1.get_balance(a3)10000
nums = [1, 2, 3, 4, 5, 6, 7, 8]nums.index(3)2
nums.append(3)class BankAccount:
def __init__(self, name, balance):
"""This is equivalent to our create_account function in bank1 module
"""
self.name = name
self.balance = balance
def get_balance(self):
return self.balance
def deposite(self, amount):
self.balance += amount
def withdraw(self, amount):
self.balance -= amount
v = BankAccount("Vikrant", 5000) # this is the class that we created now, and it can be called like a function with required argumentsv<__main__.BankAccount at 0x7fb4242cbac0>
v.deposite(1000)v.get_balance() # you don't need any argument here6000
a = BankAccount("Arcesium", 10000) # we need two arguments name and balancea<__main__.BankAccount at 0x7fb40eedd210>
a.deposite(5000) # we pass only amount a.get_balance()15000
class Stock:
def __init__(self, name, price):
"""there are some specific magic methods avaialble , if we implement those python will
do some magical operation for us!
"""
self.name = name
self.price = price
self.gain = 0
def update_price(self, newprice):
self.gain = newprice - self.price
self.price = newprice
def get_gain(self):
return self.gain
def get_price(self):
return self.pricehcl = Stock("HCL", 350) # this will automatically call __init__ methodhcl.get_gain()0
hcl.update_price(400)hcl.get_gain()50
hcl.get_price()400
class Foo:
def __init__(self, name):
self.name = name
def say_hello(self):
print("Hello", self.name)
f = Foo("Vikrant") # this calls default __init__() with no arguments
f.say_hello()Hello Vikrant
class Stock:
def __init__(self, name, price):
"""there are some specific magic methods avaialble , if we implement those python will
do some magical operation for us!
"""
self.name = name
self.price = price
self.gain = 0
def update_price(self, newprice):
self.gain = newprice - self.price
self.price = newprice
def get_gain(self):
return self.gain
def get_price(self):
return self.priceinf = Stock("INFY", 2000)inf<__main__.Stock at 0x7fb40eedd090>
print(inf)<__main__.Stock object at 0x7fb40eedd090>
class Stock:
def __init__(self, name, price):
"""there are some specific magic methods avaialble , if we implement those python will
do some magical operation for us!
"""
self.name = name
self.price = price
self.gain = 0
def update_price(self, newprice):
self.gain = newprice - self.price
self.price = newprice
def get_gain(self):
return self.gain
def get_price(self):
return self.price
def __repr__(self):
"""These should always return strings"""
return "<" + self.name + ":" + str(self.price) + ">"
def __str__(self):
"""These should always return strings"""
return self.namehcl = Stock("HCL", 500)hcl # this calls the magic method __repr__<HCL:500>
infy = Stock("Infy", 1000)
rel = Stock("Reliance", 600)stocks = [hcl, infy, rel]stocks[<HCL:500>, <Infy:1000>, <Reliance:600>]
nums[1, 2, 3, 4, 5, 6, 7, 8, 3]
print(hcl) # because it converts into str before printingHCL
hcl<HCL:500>
str(hcl)'HCL'
text = 'ttgdsgsadsajhd'text'ttgdsgsadsajhd'
print(text)ttgdsgsadsajhd
hcl # __repr__<HCL:500>
print(hcl) # __str__HCL
str(hcl)'HCL'
print(hcl)HCL
print("skjdhfkjafha")skjdhfkjafha
stocks[<HCL:500>, <Infy:1000>, <Reliance:600>]
max(stocks)TypeError: '>' not supported between instances of 'Stock' and 'Stock'
hcl > infyTypeError: '>' not supported between instances of 'Stock' and 'Stock'
def get_price(stock):
stock.get_price()max(stocks, key=get_price)TypeError: '>' not supported between instances of 'NoneType' and 'NoneType'
def get_price(s):
return s.get_price()
max(stocks, key=get_price) # one item from the list at a time will be passed to get_price function defined here<Infy:1000>
stocks[<HCL:500>, <Infy:1000>, <Reliance:600>]
sNameError: name 's' is not defined
words = "one two three four five six seven".split()words['one', 'two', 'three', 'four', 'five', 'six', 'seven']
max(words, key=len) # len is called by max for every word in given list'three'
max(stocks, key=get_price) # function get_price is called for every stock in the list <Infy:1000>
hcl > infyTypeError: '>' not supported between instances of 'Stock' and 'Stock'
class Stock:
def __init__(self, name, price):
"""there are some specific magic methods avaialble , if we implement those python will
do some magical operation for us!
"""
self.name = name
self.price = price
self.gain = 0
def update_price(self, newprice):
self.gain = newprice - self.price
self.price = newprice
def get_gain(self):
return self.gain
def get_price(self):
return self.price
def __repr__(self):
"""These should always return strings"""
return "<" + self.name + ":" + str(self.price) + ">"
def __str__(self):
"""These should always return strings"""
return self.name
def __gt__(self, another_stock):
return self.get_price() > another_stock.get_price()h = Stock("HCL", 500)
i = Stock("Infy", 1000)
r = Stock("Reliance", 700)stocks = [h , i , r]h > iFalse
max(stocks)<Infy:1000>
class Foo:
def __init__(self):
pass
def method(): # every method in class should have self!
print("Hello")f = Foo()f.method()TypeError: Foo.method() takes 0 positional arguments but 1 was given
class Foo:
def __init__(self):
pass
def method(self): # every method in class should have self!
print("Hello")f = Foo()f.method()Hello
Inheritence
class Light:
def __init__(self):
self.status = "off"
def switch_on(self):
self.status = "on"
def switch_off(self):
self.status = "off"
def get_status(self):
return self.status
hall = Light()
bedroom = Light()
kitchen = Light()
lobby = Light()class WhiteLight(Light):
color = "white"
class GreenLight(Light):
color = "green"gl = GreenLight()wl = WhiteLight()gl.get_status()'off'
gl.switch_on()gl.get_status()'on'
gl.status'on'
gl.color'green'
class PPFAcount(BankAccount):
def deposite(self, amount):
if amount > 150000:
raise Exception("Amount more than 150000 can not be deposited in PPF account!")
super().deposite(amount)
def withdraw(self, amount):
raise Exception("You can not withdraw unless the account is matured!")pa = PPFAcount("Vikrant", 1000)pa.deposite(100)pa.get_balance()1100
pa.deposite(200000)Exception: Amount more than 150000 can not be deposited in PPF account!
pa.withdraw(1000)Exception: You can not withdraw unless the account is matured!
isinstance(h, Stock)True
isinstance(pa, PPFAcount)True
isinstance(pa, BankAccount)True
isinstance([1, 2, 34], list)True
list("jhhjghhj")['j', 'h', 'h', 'j', 'g', 'h', 'h', 'j']
isinstance(5, int)True
h = Stock("hcl", 500)[1, 2, 3, 4] # this is also calling constructor of list[1, 2, 3, 4]
l = [1, 2, 3,343]isinstance(l, list)True
list(range(10)) # two different ways to create instance of claas list[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
l = [0, 2, 3, 4, 5]String formating
def greet(name):
print(f"Hello {name}, How are you doing?")greet("vikrant")Hello vikrant, How are you doing?
name = "arcesium"f"Hello {name}, welcome to python!"'Hello arcesium, welcome to python!'
def message(user, module, maxscore, score, comments):
msg = """
Hi {user},
I appreciate your efforts towards assignment of {module}.
I have evaluated your assignment and here is your score.
you have scored {score}/{maxscore}. Here are few comments about
how you have done and how to improve.
{comments}
Feel free to get in touch on slack or email if you need
any help in resolving python related queries.
Regards,
Vikrant
Pipal Academy
https://pipal.in/
""".format(user=user.capitalize(),
module=module,
maxscore=maxscore,
score=score,
comments=justify(comments))
return msg"hello {user}, how are you douing?".format(user="Vikrant")'hello Vikrant, how are you douing?'
message_template = """
Hi {user},
I appreciate your efforts towards assignment of {module}.
I have evaluated your assignment and here is your score.
you have scored {score}/{maxscore}. Here are few comments about
how you have done and how to improve.
{comments}
Feel free to get in touch on slack or email if you need
any help in resolving python related queries.
Regards,
Vikrant
Pipal Academy
https://pipal.in/"""fmt = message_template.format(user="Arcesium",
module="Module I",
score=80,
maxscore=100,
comments="You have done well otherwise, but you should focus on list comprehensions!")print(fmt)
Hi Arcesium,
I appreciate your efforts towards assignment of Module I.
I have evaluated your assignment and here is your score.
you have scored 80/100. Here are few comments about
how you have done and how to improve.
You have done well otherwise, but you should focus on list comprehensions!
Feel free to get in touch on slack or email if you need
any help in resolving python related queries.
Regards,
Vikrant
Pipal Academy
https://pipal.in/
Homework problem
Write a function triangle which will print a text based traingle of given size hint: you can try making every line a seprate string , then can have list of lines
>>> traingle(5, "*")
*
* *
* * *
* * * *
* * * * *
scripts and arguments
%%file head.py
import sys
def check_args():
first = sys.argv[1]
if first == "-n":
lines = sys.argv[2]
filename = sys.argv[3]
else:
lines = 10
filename = sys.argv[1]
return lines, filename
def head(filename, lines):
with open(filename) as f:
for i in range(lines):
print(f.readline(), end="")
lines, filename = check_args()
head(filename, lines)Overwriting head.py
!python head.py -n 3 zen.txtTraceback (most recent call last):
File "/home/jupyter-vikrant/arcesium-python-2024/head.py", line 21, in <module>
head(filename, lines)
File "/home/jupyter-vikrant/arcesium-python-2024/head.py", line 16, in head
for i in range(lines):
TypeError: 'str' object cannot be interpreted as an integer
%%file head.py
import sys
def check_args():
first = sys.argv[1]
if first == "-n":
lines = int(sys.argv[2])
filename = sys.argv[3]
else:
lines = 10
filename = sys.argv[1]
return lines, filename
def head(filename, lines):
with open(filename) as f:
for i in range(lines):
print(f.readline(), end="")
lines, filename = check_args()
head(filename, lines)Overwriting head.py
!python head.py -n 3 zen.txtThe Zen of Python, by Tim Peters
Beautiful is better than ugly.
!python head.py zen.txtThe 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.
%%file head1.py
import typer
def head(filename, lines=10):
with open(filename) as f:
for i in range(lines):
print(f.readline(), end="")
typer.run(head) # typer will take care processing argument from sys.argvOverwriting head1.py
!python head1.py --helpUsage: head1.py [OPTIONS] FILENAME
Arguments:
FILENAME [required]
Options:
--lines TEXT [default: 10]
--help Show this message and exit.
!python head1.py --lines 3 zen.txtTraceback (most recent call last):
File "/home/jupyter-vikrant/arcesium-python-2024/head1.py", line 9, in <module>
typer.run(head)
File "/home/jupyter-vikrant/arcesium-python-2024/head1.py", line 5, in head
for i in range(lines):
TypeError: 'str' object cannot be interpreted as an integer
def add(a, b):
return a+bdef add(a:int, b:int): # typehints
return a + b%%file head1.py
import typer
def head(filename, lines:int=10):
with open(filename) as f:
for i in range(lines):
print(f.readline(), end="")
typer.run(head)Overwriting head1.py
!python head1.py --helpUsage: head1.py [OPTIONS] FILENAME
Arguments:
FILENAME [required]
Options:
--lines INTEGER [default: 10]
--help Show this message and exit.
!python head1.py --lines 5 zen.txtThe Zen of Python, by Tim Peters
Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
!python head1.py zen.txtThe 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.
%%file add1.py
import typer
def add(a:int, b:int):
return a+b
typer.run(add)Overwriting add1.py
!python add1.py --helpUsage: add1.py [OPTIONS] A B
Arguments:
A [required]
B [required]
Options:
--help Show this message and exit.
%%file add10.py
import typer
def add(a:int, b:int=10):
return a+b
typer.run(add)Writing add10.py
!python add10.py --helpUsage: add10.py [OPTIONS] A
Arguments:
A [required]
Options:
--b INTEGER [default: 10]
--help Show this message and exit.
!python add10.py --b 5 30%%file add10.py
import typer
def add(a:int, b:int=10):
print(a+b)
typer.run(add)Overwriting add10.py
!python add10.py --b 5 3035
!python add10.py 3040