Illustration of Class and Object Relationship in Python OOP – Depicts how a class acts as a blueprint and an object as its instance.

A Beginner’s Guide to Object-Oriented Programming (OOP) in Python

Share this post on:

A key idea in Python is object-oriented programming, or OOP, which lets programmers design intricate, modular, and scalable applications. OOP encourages more readable and maintainable code by organizing it into reusable components. We will explore the fundamental ideas of object-oriented programming (OOP) in Python, in this blog and demonstrate their practical implementation.

What is Object-Oriented Programming?

Object-Oriented Programming (OOP) is a paradigm where everything is treated as an object that combines data (attributes) and behavior (methods). The primary goal of OOP is to simplify software development and make code more modular, flexible, and scalable.

OOP in Python revolves around creating classes, which act as blueprints for objects. Classes define properties and behaviors, while objects are instances of these classes, each with unique attributes and shared methods.

Illustration of Class and Object Relationship in Python OOP – Depicts how a class acts as a blueprint and an object as its instanc

Core Concepts of OOP

Python’s OOP system is based on four core concepts:

  1. Class: A blueprint for creating objects. It defines attributes (variables) and methods (functions).
  2. Object: An instance of a class containing data and behaviors.
  3. Inheritance: A mechanism for creating a new class based on an existing class.
  4. Polymorphism: The ability to use a function or an object in different ways.

1. Class

A class is a collection of objects. It defines the attributes (variables) and behaviors (methods) that the objects created from the class will have. Think of a class as a general template for objects that follow similar structures.

class Car:
    """Initialize the car class. (Constructor)"""
    def __init__(self, name, model):
        self.name = name
        self.model = model
       
    def __str__(self):
        """Return a string representation of the car."""
        return f"{self.name} {self.model}"

    def start_engine(self):
        """Start the car engine."""
        print("Engine started")


toyota = Car("Toyota", "Corolla")
print(toyota)

In this example:

  • Car is the class, and it has attributes like name and model, which you set in the constructor.
  • The __str__ method provides a custom string representation for the object, so when you print an instance like toyota, it outputs “Toyota Corolla”.

2. Object

An object is an instance of a class. While a class is a blueprint, an object is the actual implementation of that class with specific values for its attributes. Each object can have unique attribute values but will share the class’s structure.

toyota = Car("Honda", "Odyssey")
toyota.start_engine()

Here, toyota is an object of the Car class with unique values for name (“Honda”) and model (“Odyssey”).

3. Inheritance

Inheritance is the mechanism of creating a new class from an existing class. The new class, called the subclass, inherits attributes and methods of the existing class, known as the superclass. This helps in reusing and extending existing code without duplication.

class Car:
    """Initialize the car class. (Constructor)"""

    def __init__(self, name, model):
        self.name = name
        self.model = model

    def __str__(self):
        """Return a string representation of the car."""
        return f"{self.name} {self.model}"

    def start_engine(self):
        """Start the car engine."""
        print("Engine started")


class ElectricCar(Car):
    """Initialize the electric car class. (Constructor)"""

    def __init__(self, name, model, battery_size=75):
        """Initialize attributes of the parent class."""
        Car.__init__(self, name, model)
        self.battery_size = battery_size

    def describe_battery(self):
        """Print a statement describing the battery size."""
        print(f"This car has a {self.battery_size}-kWh battery.")


toyota =
Car("Toyota", "Corolla")
evcar = ElectricCar("Tesla", "Model S")
evcar.describe_battery()

evcar.start_engine()

In this example, Car is the base class (parent class) and ElectricCar is inherited from the Car class. We are creating an electric car as a specialized version of a car with additional functionality specific to cars, like describing battery size.

Methods:

  • describe_battery: This method prints the size of the battery, which is specific to electric cars.
  • start_engine: This method is inherited from the parent class. So, ElectricCar has access to both attributes and methods of the Car class.


4. Polymorphism

Polymorphism allows methods to be used interchangeably between different classes, making code more flexible. Polymorphism is commonly achieved through method overriding, where a subclass provides a specific implementation of a method that already exists in its superclass.

class Car:
    def drive(self):
        return "Driving a car."

class Bike:
    def drive(self):
        return "Riding a bike."

honda = Car()
ducati = Bike()

for vehicle in [honda, ducati]:
    print(vehicle.drive())

Here, both Car and Bike have a drive method, but each behaves differently. Polymorphism allows us to call drive() on each vehicle without needing to know its specific class

5. Encapsulation

Encapsulation is the practice of hiding internal details of an object and only exposing what’s necessary. This is often achieved by making attributes private (using an underscore prefix) and providing getter and setter methods to access or modify these attributes safely.

# "__" double underscore represents private attribute.

class BankAccount:
    def __init__(self, balance):
        self.__balance = balance  # private attribute
   
    def deposit(self, amount):
        if amount > 0:
            self.__balance += amount
            return f"Deposited {amount}"

    def get_balance(self):
        return f"Balance: {self.__balance}"
   
account = BankAccount(100)
print(account.get_balance())       # Output: Balance: 100
print(account.__balance)           # Raises an AttributeError

In this example:

  • The __balance attribute is private and can’t be accessed directly outside of the class.
  • It can only be accessed or modified through get_balance and deposit methods, ensuring the balance is managed correctly.
Example of Encapsulation in Python Code – Highlights code structure with private attributes and methods to demonstrate encapsulation.


6. Abstraction

Abstraction is the concept of simplifying complex systems by modeling classes with only essential attributes and methods. It hides unnecessary details and focuses on functionality, making code cleaner and easier to understand.

In Python, we often use abstract classes to create a common interface for subclasses.

import math

class Circle:
    def __init__(self, radius):
        self.__radius = radius  # Private attribute

    def area(self):
        """Calculate the area of the circle."""
        return math.pi * (self.__radius ** 2)

    def circumference(self):
        """Calculate the circumference of the circle."""
        return 2 * math.pi * self.__radius

# Create an instance of Circle
circle = Circle(5)
print(f"Area: {circle.area():.2f}")          # Output: Area: 78.54
print(f"Circumference: {circle.circumference():.2f}")  # Output: Circumference: 31.42
# Trying to access the private attribute will raise an AttributeError
# print(circle.__radius)  # This will raise an AttributeError

In this example:

  • The __radius attribute is private, so it can’t be accessed directly outside the Circle class.
  • The area and circumference can only be calculated through the area() and circumference() methods, ensuring the radius is used properly without exposing its details.

Conclusion:

Object-Oriented Programming (OOP) is a powerful paradigm that enhances code organization, readability, and maintainability. By employing the six core concepts—Class, Object, Inheritance, Polymorphism, Encapsulation, and Abstraction— you can write code that is more organized, efficient, and easier to debug, making it ideal for complex, scalable applications.

FAQs

What are the four main concepts of object-oriented programming in Python?

  • The four main concepts are classes, objects, inheritance, and polymorphism.

How does inheritance work in Python OOP?

  • Inheritance allows a class to use properties and methods of another class, creating a subclass from a superclass.

What is the difference between encapsulation and abstraction?

  • Encapsulation hides data within a class to restrict access, while abstraction simplifies code by focusing on relevant properties and methods.

How do you create a class in Python?

  • Use the class keyword followed by the class name, defining attributes and methods within the block.

Why is OOP beneficial for Python development?

  • OOP helps structure code in a way that makes it modular, easier to maintain, and scalable for complex projects.

What are some real-world examples of Python OOP?

  • Examples include game development with character classes, banking applications, and user management in software.

Refer to these resources for additional information

Python Official Documentation