Implementing Abstraction In Python

Introduction

Abstraction is one of the four pillars of Object Oriented Programming, the other three being Encapsulation, Inheritance, and Polymorphism. Abstraction allows one to focus on the essential aspects of an object while ignoring the unnecessary details. One of the most important features of Object Oriented Programming is that it models real life scenarios. An object oriented program functions exactly the way things happen in real world, This can be very effectively demonstrated using the concept of Abstraction.

Example with code

Consider that there is a class called Shape. A Shape is an abstract entity. We cannot visualize a shape independently. A shape can take different forms like Circle, Rectangle, Triangle, Polygon, and so on. So it is not possible to perform any definite operations on a shape like finding area or circumference without knowing which form it represents.

We can use the ABC metaclass and the @abstractmethod decorator from the abc module to create an Abstract Base Class called Shape as follows:

#!/usr/bin/python
# -*- coding: utf-8 -*-
class Shape(ABC):
    def __init__(self):
        print 'I am a Shape'
    @abstractmethod
    def area(self):
        pass
    @abstractmethod
    def circumference(self):
        pass

Note that the area() and circumference() methods are abstract methods. As such, they have no implementation in the Shape class.

Now if we attempt to create an instance of the Shape class, python will throw the TypeError exception as follows:

s = Shape()

TypeError: Can't instantiate abstract class Shape with abstract methods area, circumference

This makes it clear that we cannot create an instance of an abstract class. But we need to derive classes from an Abstract Base Class and provide implementation for the abstract methods.

In our case, for example, we can derive classes Circle and Rectangle from the Shape class and implement the area() and circumference() methods as follows:

class Circle(Shape):
       def __init__(self):
            super().__init__()
            print("I am a Circle")
       def area(self):
            radius = int(input("Enter the radius: "))
            print("Area of the Circle is %.2f." % ((22.0 / 7.0) * radius * radius))
       def circumference(self):
            radius = int(input("Enter the radius: "))
            print("Circumference of the Circle is %.2f." % (2 * (22.0 / 7.0) * radius))
class Rectangle(Shape):
       def __init__(self):
            super().__init__()
            print("I am a Rectangle")
       def area(self):
            length = int(input("Enter the length: "))
            breadth = int(input("Enter the breadth: "))
            print("Area of the Rectangle is %d." % (length * breadth))
       def circumference(self):
            length = int(input("Enter the length: "))
            breadth = int(input("Enter the breadth: "))
            print("Circumference of the Rectangle is %d." % (2 * (length + breadth)))

Now we can instantiate the Circle and Rectangle classes and call the area() and circumference() methods.

Following is the full python code,

# Demonstration of Abstraction
from abc import ABC, abstractmethod
class Shape(ABC):
       def __init__(self):
            print("I am a Shape")
       @abstractmethod
       def area(self):
            pass
       @abstractmethod
       def circumference(self):
            pass
class Circle(Shape):
       def __init__(self):
            super().__init__()
            print("I am a Circle")
       def area(self):
            radius = int(input("Enter the radius: "))
            print("Area of the Circle is %.2f." % ((22.0 / 7.0) * radius * radius))
       def circumference(self):
            radius = int(input("Enter the radius: "))
            print("Circumference of the Circle is %.2f." % (2 * (22.0 / 7.0) * radius))
class Rectangle(Shape):
       def __init__(self):
            super().__init__()
            print("I am a Rectangle")
       def area(self):
            length = int(input("Enter the length: "))
            breadth = int(input("Enter the breadth: "))
            print("Area of the Rectangle is %d." % (length * breadth))
       def circumference(self):
            length = int(input("Enter the length: "))
            breadth = int(input("Enter the breadth: "))
            print("Circumference of the Rectangle is %d." % (2 * (length + breadth)))
if __name__ == "__main__":
       s = Shape()
       #s.area()
       #s.circumference()
       c = Circle()
       c.area()
       c.circumference()
       r = Rectangle()
       r.area()
       r.circumference()

Note also, that if a derived class does not implement all methods of its abstract base class, then that derived also becomes abstract and cannot be instantiated. In that case we need to derive a class from the derived class and implement the abstract methods in that class.

This is demonstrated by the following program in which the class B is abstract as it does not implement the test2() method of its abstract base class A:

from abc import ABC,abstractmethod
class A(ABC):
     @abstractmethod
     def test1(self):
          pass
     @abstractmethod
     def test2(self):
          pass
class B(A):
     def test1(self):
          print("Hello")
class C(B):
     def test2(self):
         print("Welcome")
obj = C()
obj.test1()
obj.test2()

Conclusion

I hope readers find the above discussion useful in understanding the concept of abstraction as implemented in Python.


Similar Articles