Opps
Opps
Python Objects
    The object is an entity that has a state and behavior associated with it. It may be any real-world object like a mouse, keyboard,
    chair, table, pen, etc. Integers, strings, floating-point numbers, even arrays, and dictionaries, are all objects. More specifically, any
              single integer or any single string is an object.
              The number 12 is an object, the string “Hello, world” is an object, a list is an object that can hold other objects, and so on. You’ve
              been using objects all along and may not even realize it.
              An object is any entity that has attributes(properties) and behaviors(opration/methods). For example, a parrot is an object.
              It has
                   attributes - name, age, color, etc.
                   behavior - dancing, singing, etc.
              exp:human as object
                   properties--->age,gender,weight,height
                   behaviours--->eating(),sleeping(),thinking()
              exp:bank account as object
                   properties--->acn,bal,opendate,type
                   behaviour---->deposit(),withdraw()
                   etc.
              in memory,object is allocated dynamically.i.e. size of object is not known in advance and we can also manipulate this memory.
          Python Class
              A class is a template/design/blueprint for creating similar objects(instances).
              A class also represent a datatype.
In [ ]:
In [1]: # Class represents a data type
          x = 10
          print(type(x))
          y = []
          print(type(y))
          z = "Hello World"
          print(type(z))
          <class 'int'>
          <class 'list'>
          <class 'str'>
In [ ]:
             class Classname
                 code
Recommendation to define class name, first letter should be in upper case. But it is not necessary.
In [ ]:
         Note :- If we don't store object into a variable then we will lose the object and we can't use this object in the further programm, this
        type of object is called unreachable/anonymous object .
If we print refrance variable wich stored an object then it will return the address of the object.
In [ ]:
RefVar = ClassName()
2. Then :
object.method()
              Where
                   object = RefVar
                   method = function defined in the class
In [ ]:
          t1=test()
          t1.show() #by interpreter--->t1.show(t1,10)
          ---------------------------------------------------------------------------
          TypeError                                 Traceback (most recent call last)
          Cell In[4], line 6
                3         print("this is show method")
                5 t1=test()
          ----> 6 t1.show()
To solve above error we have to use self keyword as first parameter of show methode :
          t1=test()
          t1.show() #by interpreter--->t1.show(t1,10)
In [ ]:
          Note :- It does not have to be named self , you can call it whatever you like, but it has to be the first parameter of any function in
          the class.
Que.: How to create an object and call a method of created object of a class of any module?
In [ ]:
          Object Initialization :
              __init__() method in Python is used to initialize objects of a class. It is also called a constructor.
              The task of constructors is to initialize(assign values) to the data members of the class when an object of the class is created.
              Like methods, a constructor also contains a collection of statements(i.e. instructions) that are executed at the time of Object
              creation. It is run as soon as an object of a class is instantiated.
              The method is useful to do any initialization you want to do with your object.
              The __init__() method acts as a constructor. It needs a mandatory argument self, which the reference to the object.
          This is 'Constructor'
          This is 'Constructor'
          This is 'Constructor'
In [ ]:
          a1=Account()
          a2=Account()
          print(a1.acn,a1.bal)
          print(a2.acn,a2.bal)
          101 1000
          101 1000
In [ ]:
          a1=Account(101,1000)
          a2=Account(102,2000)
          print(a1.acn,a1.bal)
          print(a2.acn,a2.bal)
          101 1000
          102 2000
In [ ]:
              def deposit(self):
                  self.bal=self.bal+500
          a1=Account(101,1000)
          a2=Account(102,2000)
          print(a1.acn,a1.bal)
          print(a2.acn,a2.bal)
          a1.deposit()
          a2.deposit()
          print(a1.acn,a1.bal)
          print(a2.acn,a2.bal)
          101   1000
          102   2000
          101   1500
          102   2500
In [ ]:
                def deposit(self,amt):
                    self.bal=self.bal+amt
                def withdraw(self,amt):
                    if(self.bal>amt):
                        self.bal=self.bal-amt
                    else:
                        print("insufficient fund")
                def checkbal(self):
                    print(self.acn,self.bal)
          a1=Account(101,1000)
          a2=Account(102,2000)
          a1.checkbal()
          a2.checkbal()
          a1.withdraw(50)
          a2.withdraw(10000)
          a1.checkbal()
          a2.checkbal()
          101 1000
          102 2000
          insufficient fund
          101 950
          102 2000
In [ ]:
         Type of data members :
             - instance data members --> allocated for each object
             - class data members    --> allocated for class and shared to all objects.
             def __init__(self,a,b):
                 #instance data members
                 self.acn=a
                 self.bal=b
             def deposit(self,amt):
                 self.bal=self.bal+amt
             def withdraw(self,amt):
                 if(self.bal>amt):
                     self.bal=self.bal-amt
                 else:
                     print("insufficient fund")
             def checkbal(self):
                 print(self.acn,self.bal,self.ifsc)
         a1=Account(101,1000)
         a2=Account(102,2000)
         a1.checkbal()
         a2.checkbal()
         a1.deposit(500)
         a2.deposit(200)
         a1.checkbal()
         a2.checkbal()
         a1.withdraw(50)
         a2.withdraw(10000)
         a1.checkbal()
         a2.checkbal()
          101 1000 abc123
          102 2000 abc123
          101 1500 abc123
          102 2200 abc123
          insufficient fund
          101 1450 abc123
          102 2200 abc123
In [ ]:
Classname.data_member = value
              def __init__(self,a,b):
                  #instance data members
                  self.acn=a
                  self.bal=b
              def deposit(self,amt):
                  self.bal=self.bal+amt
              def withdraw(self,amt):
                  if(self.bal>amt):
                      self.bal=self.bal-amt
                  else:
                      print("insufficient fund")
              def checkbal(self):
                  print(self.acn,self.bal,self.ifsc)
          a1=Account(101,1000)
          a2=Account(102,2000)
          a1.checkbal()
          a2.checkbal()
          Account.ifsc="pqr321"
          a1.checkbal()
          a2.checkbal()
In [ ]:
          Type of Methods :
                  1. Instance method
                  1. class method
                  1. static method
                @classmethod
                def m2(cls):      #class method
                    print("this is m2")
                @staticmethod
                def m3():         #static method
                    print("this is m3")
          t=test()
          t.m1()            #t.m1(t)
          test.m2()         #test.m2(test)
          test.m3()         #test.m3()
          this is m1
          this is m2
          this is m3
In [ ]:
          1. Instance Method :
                Instance attributes are those attributes that are not shared by objects. Every object has its own copy of the instance attribute.
          Example :
               def mul(self):
                   print(self.a*self.b)
          obj=calculator()
          obj.mul()
20
In [ ]:
          2. Class method :
               It is one of the rarely used methods, where we use cls instead of self and we use class variables.
               @ classmethod → constructor which we use as a decorator to make a class methode.
Example :
               @classmethod
               def mul(cls):
                   print(cls.a*cls.b)
calculator.mul()
20
               @classmethod
               def mul(cls):
                   print(calculator.a*calculator.b)
          calculator.mul()
20
In [ ]:
          Static method :
               In this method, we can pass generic variables in the place of self where we can use it like defining functions normally, as you have
               to pass the arguments while calling it.
               @ staticmethod → constructor which we use as a decorator to make a static methode.
Example :
               @staticmethod
               def mul(a,b):
                   print(a*b)
calculator.mul(4,5)
20
In [ ]:
          Nested Class :
               A class is said to be Nested Class , if it's defined inside other class.
In [ ]:
In [ ]:
In [ ]:
           1. Grouping of two or more classes. Suppose you have two classes Car and Engine. Every Car needs an Engine. But, Engine won't be
              used without a Car. So, you make the Engine an inner class to the Car. It helps save code.
2. Hiding code is another use of Nested classes. You can hide the Nested classes from the outside world.
           3. It's easy to understand the classes. Classes are closely related here. You don't have to search for the classes in the code. They are
              all together.
              Inner or Nested classes are not the most commonly used feature in Python. But, it can be a good feature to implement code. The
              code is straightforward to organize when you use the inner or nested classes.
          Name= Karthik
          Dob= 10/5/1988
In [ ]:
          1. Inheritance :
          Inheritance is the procedure in which one class inherits the attributes and methods of another class.
          The class whose properties and methods are inherited is known as the Parent class . And the class that inherits the properties from
          the parent class is the Child class .
Types Of Inheritance :
              a.) Single level :- Single inheritance enables a derived class to inherit properties from a single parent class, thus enabling code
              reusability and the addition of new features to existing code.
              b.) Multilevel :- In multilevel inheritance, features of the base class and the derived class are further inherited into the new derived
              class. This is similar to a relationship representing a child and a grandfather.
c.) Multiple :- When a class can be derived from more than one base class this type of inheritance is called multiple inheritances.
d.) Hybrid :- Inheritance consisting of multiple types of inheritance is called hybrid inheritance.
              e.) Hierarchical :- When more than one derived class are created from a single base this type of inheritance is called hierarchical
              inheritance. In this program, we have a parent (base) class and two child (derived) classes.
          # Derived class
          class Child(Parent):
                  def func2(self):
                          print("This function is in child class.")
          # Driver's code
          object = Child()
          object.func1()
          object.func2()
In [ ]:
          # Base class
          class Grandfather:
          # Intermediate class
          class Father(Grandfather):
                  def __init__(self, fathername, grandfathername):
                          self.fathername = fathername
          # Derived class
          class Son(Father):
                  def __init__(self, sonname, fathername, grandfathername):
                          self.sonname = sonname
          # Driver code
          s1 = Son('Prince', 'Rampal', 'Lal mani')
          print(s1.grandfathername)
          s1.print_name()
          Lal mani
          Grandfather name : Lal mani
          Father name : Rampal
          Son name : Prince
In [ ]:
          # Base class1
          class Mother:
                  mothername = ""
                  def mother(self):
                          print(self.mothername)
          # Base class2
          class Father:
                  fathername = ""
                  def father(self):
                          print(self.fathername)
          # Derived class
          class Son(Mother, Father):
                  def parents(self):
                          print("Father :", self.fathername)
                          print("Mother :", self.mothername)
          # Driver's code
          s1 = Son()
          s1.fathername = "RAM"
          s1.mothername = "SITA"
          s1.parents()
          Father : RAM
          Mother : SITA
In [ ]:
          class Student1(School):
                  def func2(self):
                          print("This function is in student 1. ")
          class Student2(School):
                  def func3(self):
                          print("This function is in student 2.")
          # Driver's code
          object = Student3()
          object.func1()
          object.func2()
In [ ]:
          # Base class
          class Parent:
                  def func1(self):
                          print("This function is in parent class.")
          # Derived class1
          class Child1(Parent):
                  def func2(self):
                           print("This function is in child 1.")
          # Derivied class2
          class Child2(Parent):
                  def func3(self):
                          print("This function is in child 2.")
          # Driver's code
          object1 = Child1()
          object2 = Child2()
          object1.func1()
          object1.func2()
          object2.func1()
          object2.func3()
In [ ]:
              object class is the top most base class for all python classes directly or indirectly.
              incase of method conflict,MRO technique is used to resolve method call.
In [ ]:
          2. Data Encapsulation :
          Encapsulation is the process of making data private by wrapping data and its methods in a 'capsule' or unit, so that it can not be
          accessed or modified outside of that unit.
              This is achieved by making variables private inside a class. In Python we can make variables private by prefixing the variable name
              with a double underscore __ . Now data is private, and cannot be modified or changed from outside the class.
In [30]: #without encapsulation
         class emp:
             def __init__(self):
                 self.sal=20000
          e=emp()
          print(e.sal)
          e.sal=0
          print(e.sal)
          20000
          0
              def getsal(self):
                  if(True):
                      return self.__sal
                  else:
                      return 0
          e=emp()
          #print(e.__sal)        # it will raise an error because we made data private
          print(e.getsal())      # we can still access through getsal method of class.
20000
In [ ]:
          3. Polymorphism :
          Single entity in a programming language can behave in multiple ways depending on the context.
         class Arjun(Sachin):
             def play(self):
                 print("full time bowler and part time batsman")
         obj=Arjun()
         obj.play()
             def morningwalk(self):
                 print("5 km daily")
             def study(self):
                 print("using candle,diya,lamp")
         class child(person):
             def dance(self):
                 print("this is dance")
             def study(self):
                 print("zoom,youtube,google")
             def eating(self):
                 print("pizza burger")
                 super().eating()         # super() is explaine below of this program.
         obj=child()
         obj.dance()
         obj.eating()
         obj.study()
         obj=person()
         obj.study()
          this is dance
          pizza burger
          daal roti
          zoom,youtube,google
          using candle,diya,lamp
In [ ]:
super() function :
          In Python, the super() function is used to refer to the parent class or superclass. It allows you to call methods defined in the superclass
          from the subclass, enabling you to extend and customize the functionality inherited from the parent class.
In [ ]:
          2. Operator Overloading :
          Operator polymorphism, or operator overloading, means that one symbol can be used to perform multiple operations.
          # Printing the result of '+' and '*' operators for own purpose.
          print(p1+p2)       # by interpreter--->p1.__add__(p1,p2)
          print(p1*p2)       # by interpreter--->p1.__mul__(p1,p2)
          (6, 6)
          (8, 5)
In [ ]:
          4. Abstraction In OOP:
               Abstraction in python is defined as a process of handling complexity by hiding unnecessary information from the user. This is one
               of the core concepts of object-oriented programming (OOP) languages.
          Abstraction In Python
               it is a process of defining abstract classes.
               it is used to define standards for concrete classes.
Abstract Class :
               A class that contains one or more abstract methods is called an abstract class. And the sub class of ABC in Python. An abstract
               class can be considered a blueprint for other classes.
Abstract Method :
An abstract method is a method that has a declaration but does not have an implementation.
               We use an abstract class while we are designing large functional units or when we want to provide a common interface for
               different implementations of a component.
In Python, abstraction can be achieved by having/using abstract classes and methods in our programs.
               An abstract class is defined by subclassing ABC Python and declaring one or more abstract methods using the
                @abstractmethod decorator.
In [35]: # First import 'ABC' class and abstractmethod decorator from abc module.
         from abc import ABC,abstractmethod
          This is show.
          This is disp.
In [ ]:
          Example : Defining a blue print for SavingAccount class and CurrentAccount class through Account class which is an abstract
          class.
               @abstractmethod
               def deposit(self):
                   pass
               @abstractmethod
              def withdraw(self):
                  pass
              @abstractmethod
              def checkbal(self):
                  pass
          class SavingAccount(Account):
              def deposit(self):
                  print("this is deposit in saving")
              def withdraw(self):
                  print("this is withdraw in saving")
              def checkbal(self):
                  print("this is checkbal in saving")
          class CurrentAccount(Account):
              def deposit(self):
                  print("this is deposit in current")
              def withdraw(self):
                  print("this is withdraw in current")
              def checkbal(self):
                  print("this is checkbal in current")
          a1=SavingAccount()
          a1.deposit()
          a2=CurrentAccount()
          a2.deposit()
In [ ]:
          Example : This code defines an abstract base class called Polygon using the ABC (Abstract Base Class) module in Python. The
          Polygon class has an abstract method called noofsides that needs to be implemented by its subclasses.
          class Polygon(ABC):
       @abstractmethod
       def noofsides(self):
               pass
class Triangle(Polygon):
class Pentagon(Polygon):
class Hexagon(Polygon):
class Quadrilateral(Polygon):
# Driver code
R = Triangle()
R.noofsides()
K = Quadrilateral()
K.noofsides()
R = Pentagon()
R.noofsides()
K = Hexagon()
K.noofsides()
          I   have   3   sides
          I   have   4   sides
          I   have   5   sides
          I   have   6   sides
In [ ]: