Object-Oriented Programming in Python

Object-Oriented Programming (OOP) is a programming paradigm that organizes code into objects, which contain both data (attributes) and functions (methods). Python is a fully object-oriented language, allowing developers to implement OOP principles easily.


1. Understanding Classes and Objects

In Python, a class is a blueprint for creating objects. An object is an instance of a class that holds specific data.

Defining a Class and Creating an Object:

class Car:
    def __init__(self, brand, model):
        self.brand = brand
        self.model = model

    def display_info(self):
        return f"This car is a {self.brand} {self.model}"

# Creating an object
my_car = Car("Toyota", "Camry")
print(my_car.display_info())

Output:

This car is a Toyota Camry

2. The __init__ Method (Constructor)

The __init__ method is called automatically when an object is created. It initializes the object’s attributes.

class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age

p1 = Person("Alice", 30)
print(p1.name, p1.age)  # Output: Alice 30

3. Instance and Class Variables

Python allows defining both instance variables (specific to an object) and class variables (shared among all objects).

class Dog:
    species = "Canine"  # Class variable

    def __init__(self, name):
        self.name = name  # Instance variable

dog1 = Dog("Buddy")
dog2 = Dog("Charlie")

print(dog1.name, dog1.species)  # Output: Buddy Canine
print(dog2.name, dog2.species)  # Output: Charlie Canine

4. Instance Methods, Class Methods, and Static Methods

Instance Methods:

These methods operate on an instance of a class and can access instance variables.

class Cat:
    def __init__(self, name):
        self.name = name

    def speak(self):
        return f"{self.name} says Meow!"

cat = Cat("Whiskers")
print(cat.speak())  # Output: Whiskers says Meow!

Class Methods:

Class methods are defined using @classmethod and operate on the class itself.

class Animal:
    species = "Unknown"

    @classmethod
    def set_species(cls, species_name):
        cls.species = species_name

Animal.set_species("Mammal")
print(Animal.species)  # Output: Mammal

Static Methods:

Static methods do not access class or instance attributes.

class MathOperations:
    @staticmethod
    def add(a, b):
        return a + b

print(MathOperations.add(5, 3))  # Output: 8

5. Encapsulation in Python

Encapsulation restricts direct access to object attributes. Python uses underscores to indicate different access levels:

  • Public: Accessible from anywhere.
  • Protected (_variable): Should not be accessed directly but is still accessible.
  • Private (__variable): Not accessible outside the class.
class BankAccount:
    def __init__(self, balance):
        self.__balance = balance  # Private variable

    def get_balance(self):
        return self.__balance

account = BankAccount(1000)
print(account.get_balance())  # Output: 1000

6. Inheritance in Python

Inheritance allows a class (child) to inherit attributes and methods from another class (parent).

class Animal:
    def speak(self):
        return "Animal makes a sound"

class Dog(Animal):
    def speak(self):
        return "Dog barks"

dog = Dog()
print(dog.speak())  # Output: Dog barks

7. Multiple Inheritance

Python allows a class to inherit from multiple parent classes.

class A:
    def method_a(self):
        return "Method A"

class B:
    def method_b(self):
        return "Method B"

class C(A, B):
    pass

c = C()
print(c.method_a())  # Output: Method A
print(c.method_b())  # Output: Method B

8. Polymorphism in Python

Polymorphism allows methods in different classes to have the same name but different behavior.

class Bird:
    def speak(self):
        return "Bird chirps"

class Cat:
    def speak(self):
        return "Cat meows"

animals = [Bird(), Cat()]
for animal in animals:
    print(animal.speak())

Output:

Bird chirps
Cat meows

9. Abstract Classes

Abstract classes cannot be instantiated and must be inherited. They define methods that must be implemented in child classes.

from abc import ABC, abstractmethod

class Vehicle(ABC):
    @abstractmethod
    def start_engine(self):
        pass

class Car(Vehicle):
    def start_engine(self):
        return "Car engine started"

car = Car()
print(car.start_engine())  # Output: Car engine started

10. Magic Methods (__str__, __repr__, __len__, etc.)

Magic methods (also called dunder methods) allow customization of built-in Python operations.

class Book:
    def __init__(self, title):
        self.title = title

    def __str__(self):
        return f"Book title: {self.title}"

book = Book("Python Basics")
print(book)  # Output: Book title: Python Basics

11. Composition in Python

Composition is a design principle where a class contains objects of another class instead of inheriting from it.

class Engine:
    def start(self):
        return "Engine started"

class Car:
    def __init__(self):
        self.engine = Engine()

    def start_car(self):
        return self.engine.start()

car = Car()
print(car.start_car())  # Output: Engine started

Object-Oriented Programming (OOP) in Python provides a powerful way to structure code using classes and objects. Understanding OOP concepts like encapsulation, inheritance, polymorphism, and abstraction allows developers to write efficient, scalable, and reusable programs.