Object Oriented example in Python

Learn object oriented example in python with practical examples, diagrams, and best practices. Covers python development techniques with visual explanations.

Mastering Object-Oriented Programming in Python

Hero image for Object Oriented example in Python

Explore the core concepts of Object-Oriented Programming (OOP) in Python, including classes, objects, inheritance, and polymorphism, with practical examples and clear explanations.

Object-Oriented Programming (OOP) is a programming paradigm that uses 'objects' – data structures consisting of data fields and methods – to design applications and computer programs. Python is a multi-paradigm language that fully supports OOP, making it a powerful tool for building complex, maintainable, and scalable software. This article will guide you through the fundamental principles of OOP in Python, providing clear explanations and practical code examples.

Classes and Objects: The Building Blocks of OOP

At the heart of OOP are classes and objects. A class is a blueprint or a template for creating objects, defining a set of attributes (data) and methods (functions) that the objects will have. An object, on the other hand, is an instance of a class. When you create an object, you are essentially creating a concrete entity based on the class's blueprint.

class Dog:
    # Class attribute
    species = "Canis familiaris"

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

    # Instance method
    def bark(self):
        return f"{self.name} says Woof!"

# Creating objects (instances of the Dog class)
my_dog = Dog("Buddy", 3)
your_dog = Dog("Lucy", 5)

print(f"My dog's name is {my_dog.name} and he is {my_dog.age} years old.")
print(f"Your dog's name is {your_dog.name} and she is {your_dog.age} years old.")
print(my_dog.bark())
print(f"All dogs are of species: {Dog.species}")

Defining a class and creating objects in Python

Encapsulation: Bundling Data and Methods

Encapsulation is the principle of bundling data (attributes) and methods (functions) that operate on the data within a single unit, i.e., a class. It also involves restricting direct access to some of an object's components, which can prevent unintended interference and misuse of data. In Python, encapsulation is achieved through conventions rather than strict access modifiers like private or public in other languages.

class BankAccount:
    def __init__(self, account_holder, initial_balance=0):
        self.account_holder = account_holder
        self.__balance = initial_balance  # 'Private' attribute by convention

    def deposit(self, amount):
        if amount > 0:
            self.__balance += amount
            print(f"Deposited ${amount}. New balance: ${self.__balance}")
        else:
            print("Deposit amount must be positive.")

    def withdraw(self, amount):
        if 0 < amount <= self.__balance:
            self.__balance -= amount
            print(f"Withdrew ${amount}. New balance: ${self.__balance}")
        else:
            print("Invalid withdrawal amount or insufficient funds.")

    def get_balance(self):
        return self.__balance

# Usage
account = BankAccount("Alice Smith", 100)
account.deposit(50)
account.withdraw(30)
print(f"Current balance for {account.account_holder}: ${account.get_balance()}")

# Attempting to access 'private' attribute directly (discouraged)
# print(account.__balance) # This would raise an AttributeError in most cases due to name mangling

Encapsulation using a 'private' attribute convention in Python

classDiagram
    class BankAccount {
        -account_holder: str
        -__balance: float
        +deposit(amount: float)
        +withdraw(amount: float)
        +get_balance(): float
    }

Class diagram illustrating encapsulation in the BankAccount class

Inheritance: Building on Existing Classes

Inheritance is a mechanism that allows a new class (subclass or derived class) to inherit attributes and methods from an existing class (superclass or base class). This promotes code reusability and establishes a natural 'is-a' relationship between classes. For example, a 'Car' 'is-a' 'Vehicle'.

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

    def display_info(self):
        return f"Brand: {self.brand}, Model: {self.model}"

class Car(Vehicle):
    def __init__(self, brand, model, num_doors):
        super().__init__(brand, model) # Call the constructor of the parent class
        self.num_doors = num_doors

    def honk(self):
        return f"The {self.brand} {self.model} honks Beep!"

class ElectricCar(Car):
    def __init__(self, brand, model, num_doors, battery_size):
        super().__init__(brand, model, num_doors)
        self.battery_size = battery_size

    def charge(self):
        return f"The {self.brand} {self.model} is charging its {self.battery_size} kWh battery."

# Usage
my_car = Car("Toyota", "Camry", 4)
my_electric_car = ElectricCar("Tesla", "Model 3", 4, 75)

print(my_car.display_info())
print(my_car.honk())

print(my_electric_car.display_info())
print(my_electric_car.honk())
print(my_electric_car.charge())

Demonstrating single and multi-level inheritance

classDiagram
    Vehicle <|-- Car
    Car <|-- ElectricCar

    class Vehicle {
        +brand: str
        +model: str
        +display_info(): str
    }

    class Car {
        +num_doors: int
        +honk(): str
    }

    class ElectricCar {
        +battery_size: int
        +charge(): str
    }

Class diagram illustrating the inheritance hierarchy

Polymorphism: Many Forms, One Interface

Polymorphism, meaning 'many forms', allows objects of different classes to be treated as objects of a common superclass. This means you can define a common interface (e.g., a method name) in a base class, and subclasses can implement that method in their own specific ways. Python achieves polymorphism through method overriding and duck typing.

class Animal:
    def speak(self):
        raise NotImplementedError("Subclass must implement abstract method")

class Dog(Animal):
    def speak(self):
        return "Woof!"

class Cat(Animal):
    def speak(self):
        return "Meow!"

class Duck(Animal):
    def speak(self):
        return "Quack!"

# A function that takes an Animal object (or any object with a 'speak' method)
def make_animal_speak(animal):
    print(animal.speak())

# Creating instances of different animal types
dog = Dog()
cat = Cat()
duck = Duck()

# Calling the same function with different object types
make_animal_speak(dog)
make_animal_speak(cat)
make_animal_speak(duck)

Polymorphism through method overriding and duck typing