Python Object Oriented Programming – Part I

We will learn about the below concepts in Python Object Oriented Programming Part I and Part II

  • Class and Object
  • Constructor
  • Instance Variables
  • Class Variables
  • Object Methods
  • Instance Methods
  • @classmethod
  • @staticmethod
  • Inheritance
  • Method Resolution Order (MRO)
  • Abstract Classes and Methods(ABC)
  • @property, getters and setters
  • Polymorphism
  • Operator Overloading
  • Overriding

Classes & Objects

  • Classes provide a means of bundling data and functionality together. Creating a new class creates a new type of object, allowing new instances of that type to be made.
  • Each class instance can have attributes attached to it for maintaining its state
  • Classes are created using the keyword “class”
  • Object is an instance of a class

Constructor

  • The instantiation operation creates an empty object. Many classes like to create objects with instances customized to a specific initial state.
  • When a class defines an __init__() method, class instantiation automatically invokes __init__() for the newly-created class instance.
  • The constructor must have a special parameter called self. The first parameter of each method in a class must be the self which refers to the calling object. However, you can give any name to the first parameter, not necessary ‘self’.

Instance Attributes/Variables

  • Instance attributes are attributes or properties attached to an instance of a class. Instance attributes are defined in the constructor.
  • Instance attributes can be accessed using (instance name).(atttribute name)
>>> class Student:
...     def __init__(self): # constructor
...             self.name = "Girish" # instance variable
...             self.course = "Python" # instance variable
...
>>> s1 = Student()
>>> s1.name
'Girish'
>>> s1.course
'Python'
>>> s1.name = "Sanjay"
>>> s1.course = "Angular"
>>> s1.name
'Sanjay'
>>> s1.course
'Angular'
>>> class Student:
...     def __init__(self, name, course):
...             self.name = name
...             self.course = course
...
>>> s1 = Student()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: __init__() missing 2 required positional arguments: 'name' and 'course'
>>> s1 = Student("Girish","Python")
>>> s1.name
'Girish'
>>> s1.course
'Python'
>>> s1.name = "Sanjay"
>>> s1.course = "Angular"
>>> s1.name
'Sanjay'
>>> s1.course
'Angular'
>>> s2 = Student("Ramesh","PHP")
>>> s2.name
'Ramesh'
>>> s2.course
'PHP'
>>>

Class Attributes/Variables

  • Class Attribute value is the same for all instances of a class.
  • The value of class attribute is shared by all objects.
  • Class attributes are defined at class level .
  • Class attributes are accessed using the name of the class.
  • Each object of the class can have that particular class attribute accessed using object.
  • Changing the class attribute using the class name will be reflected for all the instances of a class.
  • Changing the class attribute using the instance name will not reflect elsewhere. It will only affect that particular instance.
>>> class Student:
...     msg = "Welcome to Python Programming"
...
>>> myobj = Student()
>>> myobj.msg
'Welcome to Python Programming'
>>> Student.msg
'Welcome to Python Programming'
>>> myobj2 = Student()
>>> myobj2.msg
'Welcome to Python Programming'
>>> Student.msg
'Welcome to Python Programming'
>>> Student.msg = "Welcome to Advanced Python Programming"
>>> Student.msg
'Welcome to Advanced Python Programming'
>>> myobj.msg
'Welcome to Advanced Python Programming'
>>> myobj2.msg
'Welcome to Advanced Python Programming'
>>> myobj.msg = "Hello"
>>> myobj.msg
'Hello'
>>> myobj2.msg
'Welcome to Advanced Python Programming'
>>>
>>> class StudentCount:
...     count = 0
...     def __init__(self):
...             StudentCount.count = StudentCount.count + 1
...
>>> s1 = StudentCount()
>>> s1.count
1
>>> s2 = StudentCount()
>>> s2.count
2
>>> s3 = StudentCount()
>>> s3.count
3

Object Methods

You can write as many methods as you want inside a class using the def keyword. Each method should have the first parameter as self which refers to the calling instance.

class Courses:
    courseName = 'Python'   # class variable/attribute shared by all instances

    def __init__(self, name, duration, fee, instructor): # Constructor
        print('Constructor called')
        self.name = name               # instance variable/attribute unique to each instance
        self.duration = duration       # instance variable/attribute unique to each instance
        self.fee = fee                 # instance variable/attribute unique to each instance
        self.instructor = instructor   # instance variable/attribute unique to each instance
    
    def display(self): # instance method
        print("Welcome to " + Courses.courseName ) # accessing class variable inside class method
        print("Welcome to " +self.name + " Course, Duration: " + str(self.duration) + ", Course Fee: "+ str(self.fee) + ", Course Instructor: "+ self.instructor)

myobj = Courses("Python",30,5000,"Girish")
Constructor called
myobj.display()
Welcome to Python
Welcome to Python Course, Duration: 30, Course Fee: 5000, Course Instructor: Girish

@classmethod

  • Transform a method into a class method. A class method receives the class as implicit first argument, just like an instance method receives the instance.
  • The @classmethod form is a function decorator.
  • A class method can be called either on the class (such as C.f()) or on an instance (such as C().f()). The instance is ignored except for its class. If a class method is called for a derived class, the derived class object is passed as the implied first argument.
>>> class StudentCount:
...     count = 0
...     def __init__(self):
...             StudentCount.count = StudentCount.count + 1
...     @classmethod
...     def displaycount(cls):
...             print("Total Student Count:", cls.count)
...
>>> s1 = StudentCount()
>>> s2 = StudentCount()
>>> s3 = StudentCount()
>>> StudentCount.displaycount()
Total Student Count: 3
>>> s1.displaycount()
Total Student Count: 3

class Student: 
    def __init__(self, name, age): 
        self.name = name 
        self.age = age 
      
    # a class method to create a Person object by birth year. 
    @classmethod
    def returnClassObject(cls, name, age): 
        return cls(name, age) 
    def display(self):
        print(self.name + "'s age is: " + str(self.age))
S1 = Student("Girish",30)
S1.display()
Girish's age is: 30
S1 = Student.returnClassObject("Santosh",40)
S1.display()
Santosh's age is: 40

@staticmethod

  • Transform a method into a static method.
  • A static method does not receive an implicit first argument.The @staticmethod form is a function decorator
  • A static method can be called either on the class (such as C.f()) or on an instance (such as C().f()).
>>> class Student:
...     @staticmethod
...     def display():
...             print("Welcome to Python Programming")
...
>>> Student.display()
Welcome to Python Programming
>>> s1 = Student()
>>> s1.display()
Welcome to Python Programming
>>>

References

  • https://docs.python.org/3/library/functions.html#staticmethod
  • https://docs.python.org/3/library/functions.html#classmethod
  • https://docs.python.org/3/tutorial/classes.html

Learn about Inheritance, Method Resolution Order (MRO), Abstract Classes and Methods(ABC), @property, getters and setters, Polymorphism, Operator Overloading and Overriding in the upcoming Part II of this blog article.

Happy Learning!