14  Module 2 - Day 3

Topics

For today’s practice make use of notebook module2-day3.ipynb created in your enviroment. Shut down kernel for all previous notebooks (if in runing condition) by right cliking on notbeook on left hand side file browser.

text = "Hello Python"

14.1 Classes

    Instance of class
            +---------------+
            |               |<---------methods to manipulate data
            |    data       |
            |               |<---------methods
            +---------------+
                    |
                    |
                    +------<------- methods to access data
%%file bank0.py

balance = 0

def deposit(amount):
    global balance
    balance += amount

def get_balance():# I am accessing variable balance only for reading
    return balance

def withdraw(amount):
    global balance
    balance -= amount
Overwriting bank0.py
x = 10

def increament():
    x = x + 1 # assignment operation is trying new local variable

increament()
---------------------------------------------------------------------------
UnboundLocalError                         Traceback (most recent call last)
Cell In[2], line 6
      3 def increament():
      4     x = x +1
----> 6 increament()

Cell In[2], line 4, in increament()
      3 def increament():
----> 4     x = x +1

UnboundLocalError: cannot access local variable 'x' where it is not associated with a value
import bank0
bank0.get_balance()
0
bank0.deposit(10000)
bank0.get_balance()
10000
bank0.withdraw(2000)
bank0.get_balance()
8000
%%file bank1.py

def create_account(amount, name):
    account = {"balance": amount,
               "name": name}
    return account 

def get_balance(account):
    return account['balance']

def deposit(account, amount):
    account['balance'] += amount

def withdraw(account, amount):
    account['balance'] -= amount
    
Writing bank1.py
import bank1
acc1 = bank1.create_account(1000, "Vikrant")
bank1.get_balance(acc1)
1000
acc2 = bank1.create_account(5000, "Alice")
bank1.get_balance(acc2)
5000
bank1.deposit(acc1, 5000)
bank1.withdraw(acc2, 357)
bank1.get_balance(acc1)
6000
bank1.get_balance(acc2)
4643
text
'Hello Python'
text[0]
'H'
text[0] = "h"
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
Cell In[25], line 1
----> 1 text[0] = "h"

TypeError: 'str' object does not support item assignment
class BankAccount:

    def __init__(self, amount, name): # dunder init
        # this is called as constructor of a class
        # it is like a function with special name
        # its first argument is something.. we call self
        # it does not return anything
        self.balance = amount
        self.name = name

    def deposit(self, amount):
        self.balance += amount

    def withdraw(self, amount):
        self.balance -= amount

    def get_balance(self):
        return self.balance
acc_v = BankAccount(1000, "Vikrant") # you call the class name like a function
acc_v
<__main__.BankAccount at 0x7e739c4f1f70>
type(acc_v)
__main__.BankAccount
type(text)
str
type(5)
int
nums = [1, 2, 3, 4]
type(nums)
list
d = {"a":1 , "b": 2}
type(d)
dict
nums.append(6)
nums
[1, 2, 3, 4, 6]
acc_v.deposit(5000) # while calling methods you never the self! 
acc_v.get_balance()
6000
acc_v.get_balance()
6000
acc_a = BankAccount(5000, "Alice")
acc_a.balance
5000
acc_a.name
'Alice'
class Point: # CamelCase

    def __init__(self, x, y):
        self.x = x
        self.y = y

    def get_x(self):
        return self.x

    def get_y(self): # snake_case
        return self.y
p1 = Point(0, 10)
p1.x
0
p1.y
10
p1.get_x()
0
p1.get_y()
10
Point(10, 5) # all these arguments will go to __init__
<__main__.Point at 0x7e738ac48560>
acc_v.name
'Vikrant'
acc_a.name
'Alice'

Write a class Light which has following structure

       Light
            +---------------+
            |               |<---------switch_on
            |   status=True |
            |               |<---------switch_off
            +---------------+
               |
               |
               +------<------- is_on
def add(x, y):
    return x + y
add
<function __main__.add(x, y)>
add(45, 56)
101
acc_alex = BankAccount(500, "Alex")
acc_alex.name
'Alex'
acc_alex.get_balance()
500
BankAccount.get_balance()
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
Cell In[83], line 1
----> 1 BankAccount.get_balance()

TypeError: BankAccount.get_balance() missing 1 required positional argument: 'self'
class Light:

    def __init__(self):
        self.status = False # by default the light is off

    def switch_on(self):
        self.status = True

    def switch_off(self):
        self.status = False

    def is_on(self):
        return self.status

    def __repr__(self):
        return f"Light<{self.is_on()}>"
light_hall = Light()
light_bedroom1 = Light()
light_study = Light()
light_kitchen = Light()
light_hall.switch_on()
light_kitchen.switch_on()
light_hall.switch_off()
light_study.switch_on()
lights = [light_hall, light_bedroom1, light_kitchen, light_study]
[l for l in lights if l.is_on()]
[Light<True>, Light<True>]
nums
[1, 2, 3, 4, 6]
light_hall
Light<False>
light_kitchen
Light<True>
light_study
Light<True>
light_study.is_on()
Light()
Light<False>
x = Light()
x # when I just write x without calling anything from it it will call __repr__
Light<False>
acc_v
<__main__.BankAccount at 0x7e739c4f1f70>
nums
[1, 2, 3, 4, 6]
class Point: # CamelCase

    def __init__(self, x, y):
        self.x = x
        self.y = y

    def get_x(self):
        return self.x

    def get_y(self): # snake_case
        return self.y

    def __repr__(self): # magic method
        return f"Point<{self.x}, {self.y}>"

    def __str__(self): # this will be used when we print the object/ we convert 
                       # convert using str()
        return f"({self.x},{self.y})"
origin = Point(0,0)
origin
Point<0, 0>
print(origin)
(0,0)
str(origin)
'(0,0)'
str(5)
'5'

14.2 More examples

class Chapter:

    def __init__(self, title, contents):
        self.title = title
        self.contents = contents
    
    def get_contents(self):
        return self.contents

    def __repr__(self):
        return f"Chp-{self.title}"


class Book:

    def __init__(self, title):
        self.title = title
        self.chapters = []
    
    def add_chapter(self, chapter):
        self.chapters.append(chapter)

    def __repr__(self):
        return f"Book<{self.title}>"

    def get_chapters(self):
        return self.chapters
book1 = Book("My First Book")
book1
Book<My First Book>
book1.get_chapters()
[]
intro = """
Hi All,
this is my first book.
altought the contents do nopt look 
like a book!
but yes it is my first attempt! 
"""

geting_started = """
I would like to introduce you to
python programming!
It is very simple.

but only if you practice!"""
chapter1 = Chapter("Introduction", intro)
chpater2 = Chapter("Getting Started", geting_started)
book1.add_chapter(chapter1)
book1.get_chapters()
[Chp-Introduction]
book1.add_chapter(chpater2)
book1.get_chapters()
[Chp-Introduction, Chp-Getting Started]
print(book1.get_chapters()[0].get_contents())

Hi All,
this is my first book.
altought the contents do nopt look 
like a book!
but yes it is my first attempt! 

problem

Write a class for Stock with fields name, value, high, low and mechanism to update value. Updating value will also uodate max and min automatically if required.

class Stock:

    def __init__(self, name, value):
        self.name = name
        self.value = value
        self.high = value
        self.low = value

    def set_value(self, value):
        self.value = value
        if value > self.high:
            self.high = value
        if value < self.low:
            self.low = value

    def get_value(self):
        return self.value

    def get_high(self):
        return self.high

    def get_low(self):
        return self.low

    def __repr__(self):
        return f"Stock<{self.name}-{self.value}>"
ibm = Stock("IBM", 123)
ibm
Stock<IBM-123>
ibm.set_value(125)
ibm
Stock<IBM-125>
ibm.get_high()
125
ibm.get_low()
123
ibm.set_value(120)
ibm
Stock<IBM-120>
ibm.get_high()
125
ibm.get_low()
120
ibm.set_value(124)
ibm
Stock<IBM-124>
ibm.get_high()
125
ibm.get_low()
120