This posts is a complete guide to Python OOP (Object-Oriented Programming) β both basic and advanced topics, interview-relevant insights, code examples, and a data engineering mini-project using Python OOP + PySpark.
π Python OOP: Classes and Objects (Complete Guide)
β What is OOP?
Object-Oriented Programming is a paradigm that organizes code into objects, which are instances of classes.
It helps in creating modular, reusable, and structured code.
β 1. Class and Object
πΉ Class: A blueprint for creating objects.
πΉ Object: An instance of a class with actual data.
class Car:
def __init__(self, brand, year):
self.brand = brand
self.year = year
car1 = Car("Toyota", 2020) # Object created
print(car1.brand) # Output: Toyota
β
2. __init__()
Constructor
- Special method that initializes an object
- Called automatically when the object is created
def __init__(self, name):
self.name = name
β 3. Instance Variables and Methods
- Belong to the object (not the class)
- Accessed via
self
class Person:
def __init__(self, name):
self.name = name # instance variable
def greet(self): # instance method
print(f"Hello, {self.name}")
β 4. Class Variables and Methods
- Shared across all instances
- Use
@classmethod
class Employee:
count = 0 # class variable
def __init__(self):
Employee.count += 1
@classmethod
def total_employees(cls):
return cls.count
β 5. Static Methods
- No access to
self
orcls
- Utility function tied to class
class Math:
@staticmethod
def square(x):
return x * x
β 6. Encapsulation
- Hide internal state using private/protected variables
class BankAccount:
def __init__(self):
self.__balance = 0 # private
def deposit(self, amount):
self.__balance += amount
def get_balance(self):
return self.__balance
β 7. Inheritance
- One class (child) can inherit properties and methods from another (parent). Encourages code reuse.
class Animal:
def speak(self):
print("Animal sound")
class Dog(Animal):
def speak(self):
print("Bark")
d = Dog()
d.speak() # Output: Bark
class DataSource:
def __init__(self, path):
self.path = path
def read(self):
raise NotImplementedError
class CSVSource(DataSource):
def read(self):
print(f"Reading CSV from {self.path}")
class JSONSource(DataSource):
def read(self):
print(f"Reading JSON from {self.path}")
πΌ Use Case:
Define a DataSource
base class for all sources (CSV, JSON, SQL, API) β extend it in specific classes β plug into ETL pipelines uniformly.
β 8. Polymorphism
β Concept:
Different classes implement the same method in different ways, and can be used interchangeably.
for animal in [Dog(), Animal()]:
animal.speak()
sources = [CSVSource("data.csv"), JSONSource("data.json")]
for src in sources:
src.read() # Calls appropriate method based on object type
πΌ Use Case:
Let your pipeline loop over any data source without knowing whether itβs CSV, JSON, DB, or API β only requiring it to implement a .read()
method.
β
9. Abstraction (via abc
module)
- Hide implementation; expose only interface
from abc import ABC, abstractmethod
class Shape(ABC):
@abstractmethod
def area(self):
pass
class Circle(Shape):
def area(self):
return 3.14 * 5 * 5
β 10. Special Methods / Dunder Methods
Method | Purpose |
---|---|
__init__ | Constructor |
__str__ | String representation |
__repr__ | Official string (for debugging) |
__eq__ | Custom equality comparison |
__len__ | Length of object |
__getitem__ | Indexing support |
__call__ | Callable object |
class Book:
def __init__(self, title): self.title = title
def __str__(self): return f"Book: {self.title}"
print(Book("Python")) # Book: Python
β 11. Composition vs Inheritance
- Inheritance: IS-A relationship
- Composition: HAS-A relationship
class Engine:
def start(self):
print("Engine starts")
class Car:
def __init__(self):
self.engine = Engine() # composition
def drive(self):
self.engine.start()
β Concept:
A class uses other classes inside it to build complex systems (not inheritance, but has-a).
class DataCleaner:
def clean(self, df):
return df.dropna()
class ETLJob:
def __init__(self, reader, cleaner):
self.reader = reader
self.cleaner = cleaner
def run(self):
df = self.reader.read()
return self.cleaner.clean(df)
πΌ Use Case:
An ETLJob
uses a Reader
and Cleaner
β each component can be swapped (plug-and-play). Useful in modular data pipelines.
β
12. Private (__var
) vs Protected (_var
)
Prefix | Meaning |
---|---|
_var | Protected (convention) |
__var | Private (name mangled) |
β 13. Property Decorator
Used to define getter/setter logic without changing attribute access.
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
β 14. Dataclasses (Python 3.7+)
Auto-generates __init__
, __repr__
, __eq__
from dataclasses import dataclass
@dataclass
class Point:
x: int
y: int
β 15. Custom Exceptions
class MyError(Exception):
pass
raise MyError("Something went wrong")
π§ CHEAT SHEET (INLINE)
Class β Blueprint for object
Object β Instance of class
__init__() β Constructor method
self β Refers to the current object
Instance Variable β Variable unique to object
Class Variable β Shared among all instances
@classmethod β Takes cls, not self
@staticmethod β No self or cls, utility function
Encapsulation β Hide data using __var or _var
Inheritance β Reuse parent class features
Polymorphism β Same interface, different behavior
Abstraction β Interface hiding via abc module
__str__, __repr__ β Human/dev readable display
__call__ β Make an object callable
@property β Turn method into attribute
@dataclass β Auto boilerplate class
Composition β Use other classes inside a class
Exception class β Custom error with `raise`
π§ͺ Real Use Cases in Data Engineering
Use Case | OOP Use |
---|---|
Data Source abstraction (S3, HDFS) | Base DataSource class with child implementations |
FileParser classes (CSV, JSON, Parquet) | Inheritance and polymorphism |
Pipeline steps as reusable objects | Composition of objects (Extract, Transform, Load) |
Metrics and Logging handlers | Singleton or service classes |
Configuration objects (per environment) | Encapsulation of parameters |
Letβs break down class methods, static methods, and dunder (magic) methods in Python β with clear π concepts, β use cases, and π§ͺ examples.
β
1. @classmethod
π What:
- Bound to the class, not instance
- Takes
cls
as the first argument - Can access or modify class-level variables
β Use Cases:
- Alternate constructors
- Tracking instances or metadata
- Factory patterns
π§ͺ Example:
class Book:
count = 0 # class variable
def __init__(self, title):
self.title = title
Book.count += 1
@classmethod
def get_count(cls):
return cls.count
@classmethod
def from_string(cls, data):
return cls(data.strip())
b1 = Book("Python")
b2 = Book.from_string("Data Science")
print(Book.get_count()) # Output: 2
β
2. @staticmethod
π What:
- No access to
self
orcls
- Pure utility function inside a class
- Logical grouping of functionality
β Use Cases:
- Helper methods
- Validators
- Business logic without depending on state
π§ͺ Example:
class MathTools:
@staticmethod
def square(n):
return n * n
@staticmethod
def is_even(n):
return n % 2 == 0
print(MathTools.square(4)) # 16
print(MathTools.is_even(5)) # False
β 3. Dunder (Magic) Methods
π What:
- “Double underscore” methods:
__init__
,__str__
,__len__
, etc. - Python calls them automatically
- Used to customize how your objects behave
β Most Common Dunder Methods (with use cases):
Method | Purpose | Example Use Case |
---|---|---|
__init__ | Constructor | Create object with parameters |
__str__ | String representation | print(obj) β readable output |
__repr__ | Debug representation | repr(obj) β unambiguous |
__len__ | Length | len(obj) |
__eq__ | Equality check (== ) | Custom object comparison |
__lt__ , __gt__ | Comparisons (< , > ) | Sorting custom objects |
__getitem__ | Indexing | obj[0] |
__setitem__ | Item assignment | obj[1] = value |
__call__ | Make object callable | obj() |
__iter__ , __next__ | Iteration | Custom iterable |
π§ͺ Dunder Method Examples:
class Book:
def __init__(self, title, pages):
self.title = title
self.pages = pages
def __str__(self):
return f"Book: {self.title}"
def __len__(self):
return self.pages
b = Book("Python Basics", 300)
print(b) # Book: Python Basics
print(len(b)) # 300
class Counter:
def __init__(self):
self.count = 0
def __call__(self):
self.count += 1
return self.count
c = Counter()
print(c()) # 1
print(c()) # 2
π§ Summary: When to Use What?
Feature | Use For | Has Access To |
---|---|---|
@classmethod | Alternate constructors, class config | cls |
@staticmethod | Utilities, logic helpers | None |
Dunder methods | Custom object behavior (print , == , etc.) | Auto-called by Python |
class Reader:
def read(self):
raise NotImplementedError
class CSVReader(Reader):
def __init__(self, path):
self.path = path
def read(self):
import pandas as pd
print(f"Reading from {self.path}")
return pd.read_csv(self.path)
class Transformer:
def transform(self, df):
raise NotImplementedError
class RemoveNulls(Transformer):
def transform(self, df):
return df.dropna()
class Writer:
def write(self, df):
print("Writing DataFrame")
# In real scenario, df.to_csv(), to_sql(), etc.
class ETLJob:
def __init__(self, reader, transformer, writer):
self.reader = reader
self.transformer = transformer
self.writer = writer
def run(self):
df = self.reader.read()
df = self.transformer.transform(df)
self.writer.write(df)
# Instantiate and run
reader = CSVReader("sample.csv")
transformer = RemoveNulls()
writer = Writer()
job = ETLJob(reader, transformer, writer)
job.run()
Great question! These are core pillars of Object-Oriented Programming (OOP), and they each serve different purposes in code reuse, design flexibility, and extensibility.
Letβs break it down with simple definitions, examples, and comparisons. β
π Polymorphism vs Inheritance vs Composition
Concept | Definition | Use Case | Relationship Type |
---|---|---|---|
Inheritance | One class inherits attributes/methods from another | Code reuse, subclassing | IS-A |
Polymorphism | Same interface, different behavior depending on the object | Interchangeable behaviors | Behavior overloading |
Composition | One class has objects of other classes | Combine functionality modularly | HAS-A |
𧬠1. Inheritance
βIs-Aβ relationship β A subclass is a specialized version of a parent class.
β Purpose:
- Reuse and extend functionality
- Share a common interface
π§ͺ Example:
class Animal:
def speak(self):
print("Some sound")
class Dog(Animal):
def speak(self):
print("Bark")
d = Dog()
d.speak() # Bark
π 2. Polymorphism
βMany formsβ β Different classes implement the same method name, allowing flexible interface usage.
β Purpose:
- Swap objects without changing code
- Method overriding or duck typing
π§ͺ Example:
class Cat:
def speak(self):
print("Meow")
class Dog:
def speak(self):
print("Bark")
def animal_sound(animal):
animal.speak()
animal_sound(Cat()) # Meow
animal_sound(Dog()) # Bark
β This works due to polymorphism β same method name (
speak
) used differently across classes.
π§© 3. Composition
βHas-Aβ relationship β A class contains one or more objects of other classes.
β Purpose:
- Build complex behavior by combining simple objects
- More flexible than inheritance
- Avoid tight coupling
π§ͺ Example:
class Engine:
def start(self):
print("Engine starts")
class Car:
def __init__(self):
self.engine = Engine() # HAS-A engine
def drive(self):
self.engine.start()
c = Car()
c.drive() # Engine starts
π§ Visual Comparison
Inheritance β Car IS-A Vehicle
Polymorphism β Car.drive(), Bike.drive() β same interface, different behavior
Composition β Car HAS-A Engine
π Summary Table
Feature | Inheritance | Polymorphism | Composition |
---|---|---|---|
Relationship | IS-A | Behaves-like | HAS-A |
Code reuse | β Yes | π Shared interface | β Yes |
Flexibility | β Rigid | β High | β High |
Maintenance | May lead to tight coupling | Interface-driven | Loosely coupled |
Example | class Dog(Animal) | animal.speak() | Car has Engine |
β When to Use What?
If you want to… | Use |
---|---|
Share base functionality across classes | Inheritance |
Plug and play behaviors without caring about type | Polymorphism |
Build modular components that work together | Composition |
Leave a Reply