Python

Object-Oriented Programming in Python

Many features exist in Object-Oriented programming (OOP) to develop any simple to complex application. It is used to organize the code based on the object containing attributes and behaviors, and each object is an instance of a particular class. The OOP programs are more efficient than functional programming and easy to understand. This programming approach is more suitable for developing large and complex projects that are divided into groups. Python is a very popular programming language for supporting both functional and object-oriented programming. Three main features of OOP are Inheritance, Encapsulation, and polymorphism. How to write an object-oriented program in Python from the basic and the uses of three main OOP features by using python script have described in this tutorial.

Contents:

Learning object-oriented programming in Python from the basics has been explained here by discussing the following topics with examples.

  1. Class and Object
  2. Constructor
  3. Inheritance
  4. Encapsulation
  5. Polymorphism
  6. Getter and Setter
  7. Overloading Operator and Function

Class and Object:

In object-oriented programming, class is used to declare the user-defined data structure that contains the set of attributes. The attributes can be the class variables, instance variables, and methods. The variables which are accessible by all instances of the class are called class variables. The functions which are declared inside the class are called methods. The variables defined inside any class method and accessible by the current instance of the class are called instance variables. A class is declared in Python by defining the class keyword followed by a class name and colon (:). The syntax of the class is defined below.

Syntax of the Class:

class className:
     Variables;
     Methods;

An instance or copy of a class is called an object used to access the class variables and the class methods. A class is useless without declaring an object because the class contains the description of the object only that does not allocate any memory. The object is declared by mentioning the class name with starting and ending first brackets. If the class contains any constructor method with the parameters, then you have to define the value of the parameters at the time of object declaration. The syntax of the object is given below.

Syntax of the Object:

Object_Name = Class_Name()

or

Object_Name = Class_Name(value1, value2,)

The declaration of a simple class and the object declaration of that class have shown in the following script. A class named ‘Book‘ has been declared here that contains three class variables (book_name, author_name, and price) and a method named book_discount_price(). The method will calculate the book’s price after a 5% discount and print the book’s details with the original and the discount price. The object variable named objBook has been defined in the script to create the class’s instance and call the class method.

ClassAndObject.py

# Define the class
class Book:
    # Define and initialize class variables
    book_name = "Learn Python the Hard Way"
    author_name = "Zed Shaw"
    price = 22

    # Define class method to display book details with discount price
    def book_discount_price(self):
        # Calculate the discount price after 5% discount
        d_price = self.price - self.price * 0.05
        # Print book details
        print("Book Name : {} \nAuthor Name : {}\nOriginal Price: ${}\nDiscount Price: ${}\n"
              .format(self.book_name, self.author_name, self.price, d_price))

# Create an object of the class
objBook = Book()
print("Book information after discount:")
# Call the class method
objBook.book_discount_price()

Output:

The following output will appear after executing the above script.

Constructor:

The constructor is a method of a class called automatically at the time object declaration of that class. It is mainly used to initialize the object of a variable. def keyword is used to declare any method in a Python class declaration, and the constructor method name is __init__() in Python. Two types of constructors can be declared in Python. These are the parameterless constructor and parameterized constructor. The uses of both constructors have shown in this part of this tutorial.

A. parameter-less constructor

The constructor that contains just one argument named self is called parameter-less or default constructor. No parameter is required to pass at the time of object declaration of a class that contains the parameter-less constructor. The way to declare a parameterless constructor has been shown in the following script. Here, the Customer class contains the parameter-less constructor that will initialize the four class variables when any class object will be created. Next, an object of the class named objCustomer has been declared to access the variables of the class.

default_constructor.py

# Define Customer class
class Customer:
    # Declare Constructor without parameter
    def __init__(self):
        # Initialize class variables
        self.ID = 'D-67455'
        self.name = 'Sakib Hasan'
        self.account_type = 'Saving'
        self.balance = 5000000

# Create object of the Customer class
objCustomer = Customer()
print("Customer's Basic Information:\n")
# Print the the values of the object properties
print("ID: {}\nName: {}\nAccount Type: {}\nBalance: {}"
.format(objCustomer.ID, objCustomer.name, objCustomer.account_type, objCustomer.balance))

Output:

The following output will appear after executing the above script.

B. Parameterized constructor

The constructor that contains one or more arguments with the ‘self’ argument is called the parameterized constructor. You have to pass the parameter values at the time of the object creation of the class. The way to declare parameterized constructor has been shown in the following script. Here, the Customer class is declared with a parameterized constructor and two methods. The method named balance_after_deposit() is defined to add the deposit amount with the balance. The method named balance_after_withdraw() is defined to deduct the withdrawal amount from the balance. Next, the object variable is defined to display the customer’s basic details, the balance after the deposit, and the balance after the withdraw.

parameterized_constructor.py

# Define Customer class
class Customer:
    # Declare Constructor with parameter
    def __init__(self, cust_id, cust_name, cust_balance):
        # Initialize variables
        self.ID = cust_id
        self.name = cust_name
        self.balance = cust_balance

    # Add amount with the balance
    def balance_after_deposit(self, deposit_amount):
        self.balance += deposit_amount
        # Print the current balance
        print("Deposit Ammount: {}\nCurrent Balance: {}\n".format(deposit_amount, self.balance))

    # Subtract amount from the balance
    def balance_after_withdraw(self, withdraw_amount):
        self.balance -= withdraw_amount
        # Print the current balance
        print("Withdraw Ammount: {}\nCurrent Balance: {}\n".format(withdraw_amount, self.balance))


# Create object of the customer class
objCustomer = Customer('M-231234', 'Mir Sabbir', 200000)

# Print the customer's basic information
print("Customer Details:\nID: {}\nName: {}\nOpening Balance: {}\n"
      .format(objCustomer.ID, objCustomer.name, objCustomer.balance))

# Add the deposit amount
objCustomer.balance_after_deposit(30000)

# Subtract the withdrawal amount
objCustomer.balance_after_withdraw(10000)

Output:

The following output will appear after executing the above script. Here, the opening balance is 200000. The balance becomes 220000 after adding 30000 and deducting 10000.

Inheritance:

One of the basic features of object-oriented programming is inheritance. The way to create a new class from an existing class is called inheritance. The existing class is called the parent class or base class, and the inherited new class is called the child or derived class. The child class will contain the features of the base class after inheritance. How the inheritance can be applied in the Python class has shown in the following example. In the script, the ‘Student’ is the parent class, and the ‘StudentDetails’ is the child class. Both classes have the parameterized constructors. The parent class has a method named display basic() to print the parent class’s ID, name, and email variables. The child class has a method named displayInfo() to print the values of the batch and semester variables of the child class. The constructor of the parent class is called the child class constructor. After the class declaration, the object of the parent class has been declared with three-parameter values to initialize the class variables of the parent class, and the method of the parent class has been called to display these values. Next, the child class object has been declared with three-parameter values to initialize the class variables of the child class, and the method of the child class has been called to display these values.

inheritance.py

# Define the parent class
class Student:

    # Define the parent class constructor
    def __init__(self, ID, name, email):
        # Initialize the parent class variables
        self.ID = ID
        self.name = name
        self.email = email

    # Define the parent class method
    def displayBasic(self):
        # Print the values of the parent class variables
        print("ID: {}\nName: {}\nEmail: {}".format(self.ID, self.name, self.email))


# Define the child class
class StudentDetails(Student):

    # Define child class constructor
    def __init__(self, ID, name, email, dept, batch, sem, cgpa):
        # Call the parent class constructor
        Student.__init__(self, ID, name, email)
        # Initialize the child class variables
        self.department = dept
        self.batch = batch
        self.semester = sem
        self.cgpa = cgpa

    # Define the child class method
    def displayInfo(self):
        Student.displayBasic(self)
        # Print the values of the child class variables
        print("Department: {}\nBatch: {}\nSemerter: {}"
              .format(self.department, self.batch, self.semester))


# Create the object of the parent class
objStudent = Student('674534', 'Rakib Hasan', '[email protected]')
print("Student's Basic Information:\n")
# Call the method of the parent class
objStudent.displayBasic()

# Create the object of the child class
objStudentDetails = StudentDetails('783412', 'Zannatul Ferdous', '[email protected]', 'CSE', 48, 10, 3.89)
print("\nStudent's Detail Information:\n")
# Call the method of the child class
objStudentDetails.displayInfo()
# Print a property value of the child class
print("CGPA: {}".format(objStudentDetails.cgpa))

Output:

The following output will appear after executing the above script.

Encapsulation:

Another basic feature of object-oriented programming is encapsulation. The way to hide the particular variables and methods of a class is called encapsulation. It is used to set the restriction for accessing the particular data. The main purpose of this feature is to provide data security by data hiding. Encapsulation can be implemented in Python by declaring the private or protected data members of the class. How the encapsulation can be implemented in Python has shown in the following example. In the script, The Add class has created by inheriting the Number class. A private member named ‘__result’ has declared in the child class to store the sum of two numbers, and this variable is accessible inside the child class only. The constructor of the parent class will initialize two class variables with the numbers. According to the script, the child class constructor will call the parent class’s constructor, calculate the sum of the class variables, and print the result of the addition. After the class declaration, the object of the child class has been declared. Next, the private member of the child class has used in the print function that will generate an error.

encalsulation.py

# Define the parent class
class Number:
    def __init__(self):
        # Initialize the public members of parent class
        self.n1 = 10
        self.n2 = 30

# Define the child class
class Add(Number):
    def __init__(self):
        # Call the parent constructor
        Number.__init__(self)
        '''
        Store the result of the addition in a private member
        of the child class
        '''

        self.__result = self.n1 + self.n2
        # Print the result of the addition
        print("The result of the addition = {}\n".format(self.__result))

# Create the object of the child class
objAdd = Add()
# Print the private property of the child class
print(objAdd.__result)

Output:

The following output will appear after executing the above script. When the object was defined, the constructor method was called, and the sum of 10 and 30 has printed. The error message has appeared for trying to access the private member from the outside of the class.

Polymorphism:

Another basic feature of object-oriented programming is polymorphism. The meaning of poly is ‘many’, and morphism is ‘forms’. The way to declare the same function multiple times for different purposes is called polymorphism. The coding becomes easier for using this feature of the OOP. This feature can be implemented using Python script, such as polymorphism in different classes, polymorphism in inherited classes, etc. How the polymorphism can be implemented in different classes using Python script has shown in the following example. In the script, two unrelated classes named Rectangle and Circle have been declared. Both classes have the parameterized constructor and a method named area(). Here, both classes contain the same method, but the purpose of the method is different. In the rectangular class, the constructor will initialize two variables named height and width, and the area() method will calculate the area of the rectangle. In the circle class, the constructor will initialize one variable named radius, and the area() method will calculate the area of the circle. After declaring the class, two number values will be taken from the user to pass the height and width values to the constructor of the Rectangle class at the time of object declaration. Next, the area() method of the Rectangle class will be called to print the rectangle area based on the input values. After that, one number value will be taken from the user to pass the radius value to the constructor of the Circle class at the time of the object creation. , the area() method of the Circle class will be called to print the circle area based on the input value.

polymorphism.py

# Define the Rectangle class
class Rectangle:
    # Define the constructor
    def __init__(self, height, width):
        # Initialize the class variables
        self.height = height
        self.width = width

    # Define the method to calculate rectangle area
    def area(self):
        area = self.height * self.width
        print("The area of the rectangle is {}\n".format(area))

# Define the Circle class
class Circle:
    # Define the constructor
    def __init__(self, radius):
        # Initialize the class variable
        self.radius = radius

    # Define the method to calculate circle area
    def area(self):
        area = 3.14 * self.radius * self.radius
        print("The area of the circle is {}\n".format(area))

# Take the height and width values from the user
height = int(input("Enter the height of the rectangle: "))
width = int(input("Enter the width of the rectangle: "))

# Create the object of the Rectangle class
objRectangle = Rectangle(height, width)
# Call area() method to print the rectangle area
objRectangle.area()

# Take the radius value from the user
radius = int(input("Enter the radius of the rectangle: "))
# Create the object of the Circle class
objCircle = Circle(radius)
# Call area() method to print the circle area
ob0000000000000000000000000000000000000000000000000000000000000000jCircle.area()

Output:

The following output will appear after executing the above script. According to the output, 5 has taken as height value, and 2 has taken as width value. For these values, the area of the rectan0gle is 10 (5×2) that has been printed. Next, 2 has taken as radius value, and the circle area is 12.56 (3.14x2x2) that has been printed.

Getter and Setter:

The method used to read the property’s value is called getter, and the method used to set the property’s value is called setter. In object-oriented programming, the getter is used to access the private attributes of the class, and the setter is used to set the values of the private attributes of the class. The major purposes of this feature are to ensure data encapsulation and data validation. The getter and setter can be implemented by using the normal function or @property decorator. Both ways of implementing setter and getter have been shown in this part of the tutorial.

Setter and Getter using the normal function:

The following script shows how the normal function can be used for implanting getter and setter methods. In the script, the Person class contains the custom getter and setter methods to read the values of the private class variables and set the value of the email variable that is a private member. The empty value has passed for the email variable at the time of object creation, and the custom setter method has been used to set the value of the email. The custom getter method will return all values of the class variable as a list.

custom_setter_getter.py

# Define the class
class Person:
    def __init__(self, name, email, phone):
        # Define the private member variables
        self.__name = name
        self.__email = email
        self.__phone = phone

    # Define custom getter
    def get_person_data(self):
        print("The custom getter method is called")
        return [self.__name, self.__email, self.__phone]

    # Define custom setter
    def set_person_data(self, email):
        print("The custom setter method is called")
        self.__email = email

# Create object of the class
objPerson = Person('Rifat Bin Hasan', '', '01855435626')
# Set the email value using custom setter
objPerson.set_person_data('[email protected]')
# Read all data member values using custom getter
person = objPerson.get_person_data()
# Print the return values
print("Name: {}\nEmail: {}\nPhone: {}".format(person[0], person[1], person[2]))

Output:

The following output will appear after executing the above script.

Setter and Getter using @property decorator:

The following script shows how the @property decorator can be used for implanting getter and setter methods. In the script, the getter and the setter have declared by using @property decorator to set the name variable’s value, a private class member. After declaring the class, the object of the class has been defined, and the value of the name variable has been assigned and retrieved by using setter and getter.

decorator_setter_getter.py

# Define the class
class Person:
    def __init__(self, name=''):
        # Define the private member variables
        self.__name = name

    # Define custom getter
    @property
    def name(self):
        print("The getter method is called")
        return self.__name

    # Define custom setter
    @name.setter
    def name(self, name):
        print("The setter method is called")
        self.__name = name

# Create object of the class
objPerson = Person()
# Set the email value using custom setter
objPerson.name = 'Zanifer Ali'

print("The name of the person is {}\n".format(objPerson.name))

Output:

The following output will appear after executing the above script.

Overloading Operator and Function:

When any function or operator is used for a different purpose based on the function parameter or the operands instead of the normal use of the function or operator, it is called overloading. The reusability feature can be implemented in object-oriented programming by using operator overloading and function overloading. It is a useful feature of OOP, but the excess use of this feature creates difficulty in managing the code. The simple use of operator overloading and function overloading in Python class has been shown in this tutorial.

Operator overloading:

The operator is used on two operands. The purpose of each operator is different. For example, there are many uses of the ‘+’ operator, such as it can be used for addition, combining two strings, etc. But when the ‘+’ operator is used for a different purpose, it is called operator overloading. The special functions are used for different types of operator overloading. The special function is declared using ‘__’ at the beginning and ending of the function name. Many special functions of different types of operators exist in python for operator overloading. The operator can be mathematical, comparison operator, assignment operator, etc. The use of the special function of the mathematical operator has been shown in this part of this tutorial to understand the concept of operator overloading in Python.

Mathematical Operator:

The operators which are used for arithmetic operations are called mathematical operator. These operators can be used for a special purpose by using a special function. Some special functions of the mathematical operator are mentioned below.

Operator Name Symbol Special Function
Addition + __add__(self, other)
Subtraction __sub__(self, other)
Multiplication * __mul__(self, other)
Division / __truediv__(self, other)
Modulus % __mod__(self, other)
Power ** __pow__(self, other)

Using the special function of power operator (**):

__pow__() special function is used to overload the power operator. The main purpose of the power operator is to calculate the power value of a particular number. But if we require to calculate the power values by using point values, then the general power operator will not work. Suppose there are two points (3, 2) and (2, 4). We need the sum of 32 and 24. In this case, we have to use the special function of the power operator. The __pow__() function can calculate the sum of the powers based on point values shown in the following script. The class SumOfPower contains a parameterized constructor to initialize two class variables, __pow__() function to calculate the sum of two powers based on point values, and __str__() function to print the object of the class. Next, two objects of the class have been declared. The power operator has used two object variables in the print () function to call the __pow__() function to complete the operation.

operator_overloading.py

# Define the class
class SumOfPowers:
    # Define the class constructor
    def __init__(self, n1, n2):
        self.a = n1
        self.b = n2

    # Overloading the power operator
    def __pow__(self, other):
        a = self.a ** other.a
        b = self.b ** other.b
        self.result = a + b
        return SumOfPowers(a, b)

    # string function to print object of the class
    def __str__(self):
        return str(self.a)+' + '+str(self.b)

# Create the first object
pow1 = SumOfPowers(3, 2)
# Create the second object
pow2 = SumOfPowers(2, 4)
# Calculate the powers and print the sum of powers
print("The sum of powers = ", pow1**pow2, "=", pow1.result)

Output:

The following output will appear after executing the above script. 32 is 9, and 24 is 16. The sum of 9 and 16 is 25 that is showing in the output.

Function Overloading:

Sometimes we need to write multiple methods which are quite similar but differ in some parts only. In this case, a single method can be defined to do the same tasks using function overloading. The complexity of the code can be removed, and the code becomes clearer by using function overloading. The output of the function depends on the argument passed to the function. How the function overloading can be implemented in Python has shown in the following script. The script’s main purpose is to perform four types of arithmetic operations with the default value or the values passed at the time of object creation. The method named calculate () has been used here to do the arithmetic operations. The method has been called four times in the script to do four types of tasks. When the method calls without any argument, then it will display a message only. When the method calls with ‘+’ as argument value, it will calculate the default values. When the method calls with ‘-‘ and a numeric value as argument values, then it will subtract the second default value from the argument value. When the method calls with ‘*’ and two numeric values as argument values, it will calculate two argument values.

function_overloading.py

# Define the class
class Arithmetic:
    # Define the class variable
    result = 0

    # Define the class method
    def calculate(self, operator="", number1=25, number2=35):
        # Calculate the summation
        if operator == "+":
            self.result = number1 + number2
            print('The result of the addition is {}'.format(self.result))
        # Calculate the subtraction
        elif operator == "-":
            self.result = number1 - number2
            print('The result of the subtraction is {}'.format(self.result))
        # Calculate the multiplication
        elif operator == "*":
            self.result = number1 * number2
            print('The result of the multiplication is {}'.format(self.result))
        # Calculate the division
        elif operator == "/":
            self.result = number1 / number2
            print('The result of the division is {}'.format(self.result))
        else:
            print("No operator is given")

# Create the object of the class
objArithmetic = Arithmetic()

# Call the method without argument
objArithmetic.calculate()
# Call the method with one argument
objArithmetic.calculate('+')
# Call the method with two arguments
objArithmetic.calculate('-', 50)
# Call the method with three arguments
objArithmetic.calculate('*', 2, 3)

Output:

The following output will appear after executing the above script. ‘No operator is given’ message has printed for calling the method without any argument. The sum of 25 and 35 has been printed for calling the method with one argument. The subtraction value of 50-35 has been printed for calling the method with two argument values. The multiplication value of 3 and 2 has printed for calling the method with three argument values. In this way, function overloading has been implemented in the script to use the same function multiple times.

Conclusion:

The basic object-oriented programming in Python has been explained in this tutorial by using very simple Python examples. The most common features of the OOP are discussed here to help the readers to know the way of OOP in Python and able to write Python program using class and object.

About the author

Fahmida Yesmin

I am a trainer of web programming courses. I like to write article or tutorial on various IT topics. I have a YouTube channel where many types of tutorials based on Ubuntu, Windows, Word, Excel, WordPress, Magento, Laravel etc. are published: Tutorials4u Help.