Python OOPs Concepts

Object-Oriented Programming (OOP) is a fundamental concept in Python that enables developers to create modular, maintainable, and scalable applications. By mastering the core OOP principles—classes, objects, inheritance, encapsulation, polymorphism, and abstraction—programmers can fully leverage Python’s capabilities to design effective solutions for complex problems.

What is Object-Oriented Programming in Python?

In Python, Object-Oriented Programming (OOP) is a programming paradigm that uses objects and classes. This approach represents real-world entities through concepts like inheritance, polymorphism, encapsulation, and abstraction. The primary objective of OOP is to bind data and functions that operate on that data into a single unit, which restricts access to this data from other parts of the code.

OOP Concepts in Python

1. Class in Python
2. Objects in Python
3. Polymorphism in Python
4. Encapsulation in Python
5. Inheritance in Python
6. Data Abstraction in Python

Python Class

A class is a blueprint from which objects are created. It groups related attributes and methods. For example, to manage a collection of dogs with attributes like breed and age, creating a class can help organize this information effectively.

Key Points on Python Class:

  • Classes are created using the class keyword.
  • Attributes are variables within a class.
  • Attributes can be accessed using the dot (.) operator. For example: MyClass.my_attribute

Syntax:

class ClassName:
# Statements
pass

Example:

class Animal:
pass

Python Objects

An object is an instance of a class and represents entities with a state and behavior. For example, an integer, string, or list in Python is an object.

An object consists of:

  • State: Defined by its attributes.
  • Behavior: Defined by its methods.
  • Identity: Provides a unique identity for each object.

To understand these, let’s revisit the Animal class:

class Animal:
def __init__(self, species, age):
    self.species = species
    self.age = age

Here, species and age represent the state, while behaviors might include methods that describe the animal’s actions.

Creating an Object

lion = Animal("Lion", 5)
The Python self

In Python, every method must have self as the first parameter, which represents the instance of the class.

The Python __init__ Method

The __init__ method in Python is similar to constructors in other languages. It initializes an object’s attributes.

Example with Class and Instance Attributes:

class Car:
    # Class attribute
    category = "vehicle"

    def __init__(self, make):
        self.make = make

# Object instantiation
car1 = Car("Toyota")
car2 = Car("Honda")

# Accessing class attributes
print(f"Car1 is a {car1.category}")
print(f"Car2 is also a {car2.category}")

# Accessing instance attributes
print(f"Car1 make is {car1.make}")
print(f"Car2 make is {car2.make}")

Output:

Car1 is a vehicle
Car2 is also a vehicle
Car1 make is Toyota
Car2 make is Honda

Python Inheritance

Inheritance allows one class (child class) to inherit properties and methods from another (parent class). This promotes code reuse and a logical structure.

Types of Inheritance in Python:

1. Single Inheritance: One class inherits from a single parent class.
2. Multilevel Inheritance: One class is derived from another, which is also derived from another class.
3. Hierarchical Inheritance: Multiple classes inherit from one parent class.
4, Multiple Inheritance: One class inherits from multiple classes.

Example of Inheritance:

# Parent class
class Person:
    def __init__(self, name, idnumber):
        self.name = name
        self.idnumber = idnumber

    def display(self):
        print(self.name)
        print(self.idnumber)

# Child class
class Employee(Person):
    def __init__(self, name, idnumber, salary, position):
        super().__init__(name, idnumber)
        self.salary = salary
        self.position = position

    def show_details(self):
        print(f"Name: {self.name}")
        print(f"ID Number: {self.idnumber}")
        print(f"Position: {self.position}")

emp1 = Employee("Alice", 101, 50000, "Manager")
emp1.display()
emp1.show_details()

Output:

Alice
101
Name: Alice
ID Number: 101
Position: Manager

Python Polymorphism

Polymorphism allows methods to operate on objects of various types. Here’s an example using different types of birds:

class Bird:
    def description(self):
        print("This is a bird.")

class Sparrow(Bird):
    def description(self):
        print("Sparrows can fly.")

class Penguin(Bird):
    def description(self):
        print("Penguins cannot fly.")

bird1 = Sparrow()
bird2 = Penguin()

bird1.description()
bird2.description()

Output:

Sparrows can fly.
Penguins cannot fly.

Python Encapsulation

Encapsulation wraps data and methods into a single unit, restricting access to certain components. For instance, private attributes can only be modified within their class.

Example of Encapsulation:

class BankAccount:
    def __init__(self):
        self.__balance = 1000  # Private attribute

    def deposit(self, amount):
        self.__balance += amount

    def get_balance(self):
        return self.__balance

account = BankAccount()
account.deposit(500)
print("Balance:", account.get_balance())

Output:

Balance: 1500

Data Abstraction

Data abstraction hides implementation details from the user and provides only the essential features. This can be achieved using abstract classes or private attributes.

Example of Data Abstraction

class Rectangle:
    def __init__(self, length, width):
        self.__length = length  # Private attribute
        self.__width = width    # Private attribute

    def area(self):
        return self.__length * self.__width

    def perimeter(self):
        return 2 * (self.__length + self.__width)

# Creating an object
rect = Rectangle(5, 3)

# Accessing methods
print(f"Area: {rect.area()}")
print(f"Perimeter: {rect.perimeter()}")

# Uncommenting the following line will raise an AttributeError
# print(rect.__length)

Output:

Area: 15
Perimeter: 16