Python Object-Oriented Programming Fundamentals

Understanding OOP Concepts

Object-oriented programming (OOP) is a fundamental paradigm in Python that enables developers to create modular, reusable, and maintainable code. This article explores the core concepts of OOP in Python including classes, objects, inheritance, polymorphism, and encapsulation.

Classes and Objects

A class serves as a blueprint for creating objects. It defines the attributes (data) and methods (functions) that objects instantiated from the class will possess.

Class Definition

class BankAccount:
    # Class variable - shared across all instances
    bank_name = "Global Bank"
    
    # Constructor method
    def __init__(self, account_number, owner_name, initial_balance=0):
        # Instance variables - unique to each instance
        self.account_number = account_number
        self.owner_name = owner_name
        self.balance = initial_balance
    
    # Instance method
    def deposit(self, amount):
        if amount > 0:
            self.balance += amount
            return f"Deposited {amount}. New balance: {self.balance}"
        return "Invalid deposit amount"
    
    def withdraw(self, amount):
        if amount > 0 and amount <= self.balance:
            self.balance -= amount
            return f"Withdrew {amount}. New balance: {self.balance}"
        return "Invalid withdrawal amount"
    
    def get_balance(self):
        return self.balance

Creating Objects

# Instantiation - creating an object from a class
account1 = BankAccount("ACC001", "Alice Johnson", 5000)
account2 = BankAccount("ACC002", "Bob Smith", 10000)

# Accessing attributes
print(account1.owner_name)  # Alice Johnson
print(account2.balance)     # 10000

# Calling methods
print(account1.deposit(1500))   # Deposited 1500. New balance: 6500
print(account2.withdraw(2000))  # Withdrew 2000. New balance: 8000

The Role of self

The self parameter in Python methods refers to the current instance of the class. When a method is called, Python automatically passes the instance as the first argument. This allows each object to access and modify its own attributes.

class Calculator:
    def __init__(self, model):
        self.model = model
    
    def add(self, a, b):
        print(f"Using {self.model} calculator:")
        return a + b

calc = Calculator("Scientific")
result = calc.add(5, 3)  # self is automatically passed
print(result)  # 8

Class Variables vs Instance Variables

Understanding the distinction between class and instance variables is crucial:

class Employee:
    # Class variable - shared by all instances
    company_name = "Tech Corporation"
    
    def __init__(self, employee_id, name):
        # Instance variable - unique to each instance
        self.employee_id = employee_id
        self.name = name
    
    @classmethod
    def get_company(cls):
        return cls.company_name

emp1 = Employee("E001", "Alice")
emp2 = Employee("E002", "Bob")

print(Employee.company_name)  # Tech Corporation
print(emp1.company_name)   # Tech Corporation (accessed from class)

# Modification affects all instances
Employee.company_name = "New Tech Corp"
print(emp1.company_name)  # New Tech Corp
print(emp2.company_name)  # New Tech Corp

Inheritence

Inheritance allows a new class to inherit attributes and methods from an existing class. The new class is called a subclass or derived class, and the existing class is the superclass or base class.

Single Inheritance

# Base class
class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age
    
    def introduce(self):
        return f"I am {self.name}, {self.age} years old"

# Derived class
class Student(Person):
    def __init__(self, name, age, student_id):
        super().__init__(name, age)  # Call parent constructor
        self.student_id = student_id
    
    def study(self, subject):
        return f"{self.name} is studying {subject}"

student = Student("Alice", 20, "S12345")
print(student.introduce())  # I am Alice, 20 years old
print(student.study("Python"))  # Alice is studying Python

Multiple Inheritance

Python supports multiple inheritance, allowing a class to inherit from multiple parent classes:

class Worker:
    def work(self):
        return "Working..."

class Learner:
    def learn(self):
        return "Learning..."

class Intern(Worker, Learner):
    def daily_task(self):
        return f"{self.work()} and {self.learn()}"

intern = Intern()
print(intern.daily_task())  # Working... and Learning...

Method Resolution Order (MRO)

When multiple inheritance is used, Python uses MRO to determine the order in which base classes are searched:

class A:
    def greet(self):
        return "Hello from A"

class B(A):
    def greet(self):
        return "Hello from B"

class C(A):
    def greet(self):
        return "Hello from C"

class D(B, C):
    pass

d = D()
print(d.greet())  # Hello from B
print(D.__mro__)  # Shows the inheritance chain

Polymorphism

Polymorphism allows objects of different classes to be treated uniformly through a common interface.

Using Inheritance

class Bird:
    def fly(self):
        return "Some birds can fly"

class Penguin(Bird):
    def fly(self):
        return "Penguins cannot fly"

class Sparrow(Bird):
    def fly(self):
        return "Sparrows can fly"

def demonstrate_flight(bird):
    print(bird.fly())

bird = Bird()
penguin = Penguin()
sparrow = Sparrow()

demonstrate_flight(bird)    # Some birds can fly
demonstrate_flight(penguin)   # Penguins cannot fly
demonstrate_flight(sparrow)  # Sparrows can fly

Duck Typing

Python follows the principle: "If it walks like a duck and quacks like a duck, it's a duck." This means objects are judged by their behavior rather than their type:

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

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

def make_speak(obj):
    print(obj.speak())

duck = Duck()
dog = Dog()

make_speak(duck)  # Quack!
make_speak(dog)  # Woof!

Encapsulation

Encapsulation restricts direct access to certain attributes, providing controlled interfaces for data manipulation.

Private Variables

Python uses name mangling to create private attributes:

class SecureVault:
    def __init__(self, password):
        self.__secret_code = password  # Private attribute
    
    def verify(self, code):
        return self.__secret_code == code
    
    def __private_method(self):
        return "This is private"

vault = SecureVault("secret123")
print(vault.verify("secret123"))  # True
# vault.__secret_code  # AttributeError - cannot access directly
# Access via name mangling
print(vault._SecureVault__secret_code)  # secret123

Property Decorator

The @property decorator provides controlled access to attributes:

class Temperature:
    def __init__(self, celsius):
        self.celsius = celsius
    
    @property
    def fahrenheit(self):
        return (self.celsius * 9/5) + 32
    
    @fahrenheit.setter
    def fahrenheit(self, value):
        self.celsius = (value - 32) * 5/9

temp = Temperature(0)
print(temp.fahrenheit)  # 32.0
temp.fahrenheit = 100
print(temp.celsius)  # 37.777...

Class Methods and Static Methods

class MathUtils:
    @staticmethod
    def add(x, y):
        return x + y
    
    @classmethod
    def description(cls):
        return f"This is a {cls.__name__} class"

print(MathUtils.add(5, 3))          # 8
print(MathUtils.description())       # This is a MathUtils class

Composition

Composition creates "has-a" relationships, where one class contains another as a component:

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

class Car:
    def __init__(self, model):
        self.model = model
        self.engine = Engine()  # Composition
    
    def start_car(self):
        return f"{self.model}: {self.engine.start()}"

car = Car("Tesla Model 3")
print(car.start_car())  # Tesla Model 3: Engine started

Summary

Object-oriented programming in Python provides several key mechanisms:

Concept Purpose
Classes Blueprints for creating objects
Objects Instances with unique attribute values
Inheritance Code reuse through parent-child relationships
Polymorphism Uniform treatment of different object types
Encapsulation Controlled access to internal data

These concepts work together to create clean, maintainable, and extensible software designs.

Tags: python object-oriented programming OOP Classes

Posted on Fri, 24 Jul 2026 16:30:15 +0000 by Spogliani