Chapter 16 (Oop) 1.intro Code:: Class Def
Chapter 16 (Oop) 1.intro Code:: Class Def
1.intro: oop is just a style/way to write a code. It is very helpful to create a real world program.
code:
#objectives
#what is class
#how to create class
#what is INIT method or constructor
#what are ATTRIBUTES,INSTANCE VARIABLE
# how to create our object
class person:#def class
#any function define in class called as method
def __init__(self,first_name,last_name,age):#first arguement in "init" fu
nction is object . self is object and first_name,last_name,age are attributes
#instance variables
self.first_name=first_name# self.first_name, self.last_name,self.age a
re instance varibles
self.last_name=last_name
self.age=age
p1=person("Ankush","Singh",20)#p1,p2 is object
p2=person("Abhay","Kumar",21)
print(p1.first_name)#when we call p1 then self =p1
output:
Ankush
Kumar
small exercise:
code:
class laptop:
def __init__(self,brand_name,model_name,price):
self.brand_name = brand_name
self.model_name = model_name
self.price = price
self.laptop_name= brand_name+" "+model_name
l1=laptop("dell","inspiron 15 3576",55000)
l2=laptop("hp","pavallion ",89000)
l3=laptop("acer","predator",59000)
print(l1.brand_name,l2.model_name)
print(l1.laptop_name)
output:
dell pavallion
2.Instance method:
code:
#instance or object method
class person:
def __init__(self,first_name,last_name,age):#init object used to construct
or create our object
self.first_name=first_name
self.last_name=last_name
self.age=age
def full_name(self):#instance method here there is no need to pass more at
tributes but only self
return f"{self.first_name} {self.last_name}"
p1=person("Ankush","singh",20)
p2=person("Nayan","Arora",20)
print(p1.full_name())
print(p2.first_name)
output:
Ankush singh
Nayan
def discount(self,n):
return self.price- (self.price*n)/100
l1=laptop("dell","inspiron 15 3576",55000)
l2=laptop("hp","pavallion ",89000)
l3=laptop("acer","predator",59000)
print(l1.brand_name,l2.model_name)
print(l1.laptop_name)
print(l2.discount(10))
output:
dell pavallion
80100.0
3.class variable:
code:
#class variable:
#class circle
#area and circumference
class circle:
pi=3.14#class variables
def __init__(self,radius):
self.radius=radius
def calc_circumference(self):
return 2*circle.pi*self.radius
c1=circle(4)
c2=circle(3)
print(c1.calc_circumference())
print(c2.calc_circumference())
output:
25.12
18.84
class laptop:
discount=10
def __init__(self,brand_name,model_name,price):
self.brand_name = brand_name
self.model_name = model_name
self.price = price
self.laptop_name= brand_name+" "+model_name
def apply_discount(self):
discount_price=(self.discount/100)*self.price
return self.price- discount_price
l1=laptop("dell","inspiron 15 3576",55000)
l2=laptop("hp","pavallion ",89000)
l3=laptop("acer","predator",59000)
l2.discount=20# to give differnt discount than class discount on special lap
top we use self.discount
print(l1.brand_name)
print(l1.laptop_name)
print(l1.apply_discount())
print(l2.apply_discount())
#how to know how many variables our object has
print(l2.__dict__)
code:
dell
49500.0
71200.0
{'brand_name': 'hp', 'model_name': 'pavallion ', 'price': 89000, 'laptop_name': 'hp pavallion ', 'discount': 20}
p1=Person("ankush","singh",20)#when we create object init func. or constructor
call
#suppose if we create one obejct or instance then 1 time init call , if 3 obj
ect then 3 times call init func.
p2=Person("rohit","singh",24)
p3=Person("mohit","singh",25)
print(Person.count_instance)
output:
3
4.Class method:
Code:
class Person:
count_instance=0 #class variable or class attributes
def __init__(self,first_name,last_name,age):#self represent the object
Person.count_instance+= 1
self.first_name=first_name
self.last_name=last_name
self.age=age
@classmethod
def count_instance(cls):
return f" you have {cls.count_instance} instance of {cls.__name__} cla
ss"
p1=Person("ankush","singh",20)#when we create object init func. or constructor
call
#suppose if we create one obejct or instance then 1 time init call , if 3 obj
ect then 3 times call init func.
p2=Person("rohit","singh",24)
p3=Person("mohit","singh",25)
print(Person.count_instance())
output:
you have 3 instance of Person class
p1=Person("ankush","singh",20)#when we create object init func. or constructor
call
#suppose if we create one obejct or instance then 1 time init call , if 3 obj
ect then 3 times call init func.
p2=Person("rohit","singh",24)#this is simple to create obejct
p3=Person("mohit","singh",25)
# suppose if we want to create the object from diiferrnt method
#p3=Person("ankit,singh,29")#from string we use class method as constructor to
ceate our object
p4=Person.from_string("ankit,singh,29")
print(p4.first_name)
output:
Ankit
6.static method :
Code:
#static method: we use static method decorator
class Person:
count_instance=0 #class variable or class attributes
def __init__(self,first_name,last_name,age):#self represent the object
Person.count_instance+= 1
self.first_name=first_name
self.last_name=last_name
self.age=age
@staticmethod
def hello(): #it have no relation with class but it may have logical relat
ion with class
return "hello,static method called"
p1=Person("ankush","singh",20)
p2=Person("rohit","singh",24)
p3=Person("mohit","singh",25)
print(Person.hello())
output:
hello,static method called
def full_name(self):
return f"{self.brand} {self.model_name}"
def calling(self,phone_number):
return f"calling {self.brand} {phone_number}"
p1=Phone("redmi","redmi4",10000)
p2=Phone("apple","iphone 10R",80000)
print(p2.calling(9711414984))
#abstraction:
#suppose we have one list and we want to sort that list
l=[25,6,3,4,7889,977]
l.sort()#we sort using sort function but we dpnt know its implementaton how it
s sort we just sort by sort functions so this is abstraction . Abstraction mea
ns to hiding the real implementation or complexity of any function (like sort,
append )from the user
print(l)
#namingconvention:
#_name like self._price=price# convention of private name(means dont change th
is name in code but it can do because in python all are public)
#__name__#called "dunder"(magic)method
#name mangling: __name(python change the name of this attribute)
#it change and give _classname__attribute name like as we do in price in this
code
#print(p1._price)#it gives error give AttributeError: 'Phone' object has no a
ttribute '_price' but we have this attribute .this is done because of name man
gling(python change the name of this attributes)
print(p1.__dict__)
print(p1._Phone__price)
output:
calling apple 9711414984
10000
Code:
#setter and property decorator:setter decorator is use just after property dec
orator and from property decorator we can call function as instance varibles
# some problem
#1problem: if we give negative price then in output we want 0 because practica
lly -price is not possible we over come this problem by using max func
class Phone:
def __init__(self,brand,model_name,price):
self.brand=brand
self.model_name=model_name
self._price=max(price,0)
self.complete_spec=f"{self.brand} {self.model_name} and {self._price}"
def full_name(self):
return f"{self.brand} {self.model_name}"
def calling(self,phone_number):
return f"calling {self.brand} {phone_number}"
p1=Phone("Xiaomi","redmi4",-10000)
p2=Phone("apple","iphone 10R",80000)
print(p1.brand)
print(p1.model_name)
print(p1._price)
print(p1.complete_spec)
#2nd problem
#if we change the price p1._price=9000 in the above code then we get output th
is
#output
#Xiaomi
#redmi4
#9000 this price change but in complete spec old price is shown this can be fi
x by using instance method or making another function
#Xiaomi redmi4 and 10000#
class Phone:
def __init__(self,brand,model_name,price):
self.brand=brand
self.model_name=model_name
self._price=max(price,0)
@property#from property decorator we can call function as instance varible
s
def complete_spec(self):
return f"{self.brand} {self.model_name} and {self._price}"
def full_name(self):
return f"{self.brand} {self.model_name}"
def calling(self,phone_number):
return f"calling {self.brand} {phone_number}"
p1=Phone("Xiaomi","redmi4",10000)
p2=Phone("apple","iphone 10R",80000)
print(p1.brand)
print(p1.model_name)
p1._price=1000
print(p1._price)
#print(p1.complete_spec())#but if we want to call complete_spec()function as i
nstance variable we use "property decorator"
print(p1.complete_spec)
#3rd problem
#p1._price=-9000 if we negative price then output is
#Xiaomi
#redmi4
#-9000
#Xiaomi redmi4 and -9000 we can overcome this problem by using "setter decorat
or"
#we use setter decorator to set the price and setter decorator is use just aft
er decorator
class Phone:
def __init__(self,brand,model_name,price):
self.brand=brand
self.model_name=model_name
self._price=max(price,0)
@property#from property decorator we can call function as instance varible
s
def complete_spec(self):
return f"{self.brand} {self.model_name} and {self._price}"
@property
def price(self):
return self._price
@price.setter
def price(self,new_price):
self._price=max(new_price,0)
def full_name(self):
return f"{self.brand} {self.model_name}"
p1=Phone("Xiaomi","redmi4",10000)
p2=Phone("apple","iphone 10R",80000)
print(p1.brand)
print(p1.model_name)
p1._price=-777
print(p1.price)
print(p1.complete_spec)
Output:
Xiaomi
redmi4
Xiaomi
redmi4
1000
Xiaomi
redmi4
9.inheritance intro:
Code:
class Phone:#base class/parent class
def __init__(self,brand_name,model_name,price):
self.brand_name=brand_name
self.model_name=model_name
self.price=max(price,0)
def full_name(self):
return f"{self.brand_name} {self.model_name}"
def make_a_call(self,number):
return f"calling {number}"
#and we want to make a new have all method of phone class and also have new at
tributes . so for this we will inherit phone class in smart phone class
class Smartphone(Phone):#child class,derived class
def __init__(self,brand_name,model_name,price,ram,internal_memory,rear_cam
era):
#Phone.__init__(self,brand_name,model_name,price)#uncommon way
super().__init__(brand_name,model_name,price)
self.ram=ram
self.internal_memory=internal_memory
self.rear_camera=rear_camera
nokia=Phone("nokia","1100",1200)
samsung=Smartphone("samsung","j2",10000,"4gb","64gb","20 mp")
print(nokia.price)
print(samsung.full_name())
print(samsung.rear_camera)
print(help(Smartphone))
output:
1200
samsung j2
20 mp
class Smartphone(Phone)
| Smartphone
| Phone
-- More --
def full_name(self):
return f"{self.brand_name} {self.model_name}"
def make_a_call(self,number):
return f"calling {number}"
#and we want to make a new have all method of phone class and also have new at
tributes . so for this we will inherit phone class in smart phone class
class Smartphone(Phone):#child class,derived class
def __init__(self,brand_name,model_name,price,ram,internal_memory,rear_cam
era):
#Phone.__init__(self,brand_name,model_name,price)
super().__init__(brand_name,model_name,price)
self.ram=ram
self.internal_memory=internal_memory
self.rear_camera=rear_camera
class Flagship(Smartphone):
def __init__(self,brand_name,model_name,price,ram,internal_memory,rear_cam
era,processor,front_camera):
super().__init__(brand_name,model_name,price,ram,internal_memory,rear_
camera)
self.front_camera=front_camera
self.processor=processor
nokia=Phone("nokia","1100",1200)
samsung=Smartphone("samsung","j2",10000,"4gb","64gb","20 mp")
oneplus=Flagship("oneplus","5",45667,"6gb","128gb","44mp","2.1 ghz","18mp")
print(f"processor is {oneplus.processor},front camera is {oneplus.front_camera
}")
print(help(Flagship))#mro
output:
processor is 2.1 ghz,front camera is 18mp
class Flagship(Smartphone)
| Flagship
| Smartphone
-- More --
def full_name(self):
return f"{self.brand_name} {self.model_name}"
def make_a_call(self,number):
return f"calling {number}"
#and we want to make a new have all method of phone class and also have new at
tributes . so for this we will inherit phone class in smart phone class
class Smartphone(Phone):#child class,derived class
def __init__(self,brand_name,model_name,price,ram,internal_memory,rear_cam
era):
#Phone.__init__(self,brand_name,model_name,price)
super().__init__(brand_name,model_name,price)
self.ram=ram
self.internal_memory=internal_memory
self.rear_camera=rear_camera
class Flagship(Smartphone):
def __init__(self,brand_name,model_name,price,ram,internal_memory,rear_cam
era,processor,front_camera):
super().__init__(brand_name,model_name,price,ram,internal_memory,rear_
camera)
self.front_camera=front_camera
self.processor=processor
def full_name(self):
return f"{self.brand_name} {self.model_name} {self.front_camera} and
{self.processor}"
nokia=Phone("nokia","1100",1200)
samsung=Smartphone("samsung","j2",10000,"4gb","64gb","20 mp")
oneplus=Flagship("oneplus","5",45667,"6gb","128gb","44mp","2.1 ghz","18mp")
print(oneplus.full_name())
#buit in functio:
#isinstance: it is used when we want to want to any object is belong to this c
lass or not, it gives true or false
print(isinstance(oneplus,Smartphone))#actually this is obect of flagship class
but it flagship class inherit smartphone and phone class then this object is a
lso of samrtphone and phone class
print(isinstance(samsung,Flagship))#it give false
#is subclass function
print(issubclass(Smartphone,Flagship))#smartphone class is not subclass of fla
gship but it is a subclass of phone
print(issubclass(Flagship,Smartphone))#flagship is subclass of smartphone and
phone class then it give true
print(issubclass(Flagship,Phone))
output:
True
False
False
True
True
13.multilple inheritance:
code:
#multiple inheritance
class A:
def class_a_method(self):
return " i am just a class A method"
def hello(self):
return " hello from class A"
class B:
def class_b_method(self):
return " i am just a class B method"
def hello(self):
return " hello from class B"
class C(A,B):# class C have all method and attributes of class A and class B
pass
#how to create instance or object of class A and B
instance_a=A()
instance_c=C()
print(instance_c.class_a_method())
print(instance_c.class_b_method())
print(instance_c.hello())#it call class A hello instead of class B because of
mro if we write C(B,A) then class b hello print because it will first check cl
ass C then class B instance variable and method then if it didnot find in clas
sB then it will go in class A due to mro.
print(help(C))
#print(C.mro())
#print(C.__mro__)
output:
class C(A, B)
| C
| A
| B
| builtins.object
-- More --
def phone_name(self):
return f"{ self.brand} {self.model_name}"
#str,repr
def __str__(self):
return f"{self.brand} {self.__price} {self.model_name}"
# def __repr__(self):
# return f"{self.brand} {self.__price} {self.model_name}"
my_phone=Phone("nokia","1100",1000)
print(my_phone)
# we can call it repr and str like a function
print(str(my_phone))
#print(repr(my_phone))
output:
nokia 1000 1100
nokia 1000 1100
code: when both str and repr used simultaneously then in output we get return of str
function if we write print(my_phone)
#dunder method:it is start with __method name__ like a init method
#__str__:string and it is commonly used ,__repr__: representation and it is m
ostly used by developer and it return something wich is object . So if you wan
t to print the object through netho used repr method and if we both use simult
aneously then str callinstead of repr.
# __len__:length
class Phone:
def __init__(self,brand,model_name,price):
self.brand=brand
self.model_name=model_name
self.__price=price
def phone_name(self):
return f"{ self.brand} {self.model_name}"
#str,repr
def __str__(self):#for normal user
return f"{self.brand} {self.__price}"
def __repr__(self):#for developer to do debuugging
return f"Phone (\"{self.brand}\" {self.__price} \"{self.model_name}\")
"
def __len__(self):
#return len(self.model_name) or return len(price) it give error
return len(self.__repr__())# we meausre only length of method or funct
ion not unstance variable in init method
my_phone=Phone("nokia","1100",1000)
print(my_phone)#str is call when we both use str and repr
# we can call it repr and str like a function
print(str(my_phone))
print(repr(my_phone))#if we copy the output of repr then it give object
print(len(my_phone))
output:
nokia 1000
nokia 1000
27
14.operatoroverloading:
code:
#operator overloading and polymorphism
class Phone:
def __init__(self,brand,model_name,price):
self.brand=brand
self.model_name=model_name
self.price=price
def __add__(self,other):#self for 1st phone and other for 2nd phone
return self.price + other.price
my_phone=Phone("nokia","1100",1000)
my_phone2=Phone("nokia","1200",1400)
#suppose if we want to add ,multiply ,sub and more thing the price of both pho
ne ant this is done by using operator overloading
print(my_phone+my_phone2)
output:
2400