Python

P
PythonHub
Progress 0%

Python

  • Home
  • History of Python
  • Applications of Python
  • Introduction To Python
    • What is Python
    • Character Set
    • Tokens in Python
    • Python Execution Mode
    • Variable And Identifiers
    • Data Types in Python
    • Operators And Expressions
    • Constants in Python
    • Assignment Statement
    • Input / Output in Python
    • Simple Python Scripts
    • Namespace in Python
    • šŸ“ Assignments
  • Operators in Python
    • Arithmetic Operators
    • Assignment Operators
    • Shorthand Assignment Operators
    • Relational Operators
    • Logical Operators
    • Bitwise Operators
    • Special Operators
    • šŸ“ Assignments
  • Input Output in Python
    • Accept Input
    • Output Formatting
    • šŸ“ Assignments
  • Conditional Statement
    • Decision Making
    • if Statement
    • IF-ELSE STATEMENT
    • IF-ELSE LADDER
    • NESTED IF-ELSE
    • Short Hand IF-ELSE
    • šŸ“ Assignments
  • Loops
    • Introduction to Loops
    • While Loop
    • Nested While Loop
    • šŸ“ While Loop Assignments
    • For Loop
    • For Loop Examples
    • Nested For Loop
    • Nested For Loop Examples
    • Infinite While Loops
    • Infinite For Loops
    • Break, Continue and Else in Loops
    • Difference Between For and While Loop
    • For Each Loop
    • šŸ“ For Each Assignments
    • šŸ“ All Loops Assignments
  • List
    • List in Python
    • Access List Elements
    • List Functions
    • Iterate (Loop) List
    • List Comprehension
    • šŸ“ Assignments
  • Tuple
    • Tuple in Python
    • Access Tuple Elements
    • Tuple Functions
    • Iterate (Loop) Tuple
    • Unpack Tuple
    • Tuple Comprehension
    • šŸ“ Assignments
  • Set
    • Set in Python
    • Access Set Elements
    • Set Methods
    • Iterate (Loop) Set
    • Pack/Unpack Set
    • Set Comprehension
    • šŸ“ Assignments
  • Dictionary
    • Dictionary
    • Access Dictionary Items
    • Dictionary Methods
    • Iterate (Loop) Dictionary
    • Formatting Dictionaries
    • Nested Dictionaries
    • Dictionary Comprehension
    • šŸ“ Assignments
  • Diff List Tuple Set Dictionary
    • List vs Tuple
    • List vs Set
    • List vs Dictionary
    • Tuple vs Set
    • Tuple vs Dictionary
    • Dictionary vs Set
    • šŸ“ Assignments
  • Exception
    • Error vs Exception
    • Types of Exception
    • Exception Handling
    • User Defined Exception
    • Logging Exception
    • šŸ“ Assignments
  • Functions
    • Introduction to Functions
    • Modular Programming
    • Types of Functions
    • Inbuilt Functions
    • Need For User-Defined Function
    • Elements of User Defined Function
    • Function Arguments
    • Nesting of Functions
    • Recursion
    • Global Local and Non Local
    • Python Lambda Functions
    • šŸ“ Assignments
  • Python Module
    • Introduction to Module
    • Inbuilt Modules in Python
    • User Defined Module
    • šŸ“ Assignments
  • File Handling
    • Introduction to Files
    • Create File
    • Read Files
    • Write to File
    • Rename File
    • Copy File
    • Move File
    • List Files in Directory
    • Binary Files
    • Zipping and Unzipping Files
    • šŸ“ Assignments
  • Strings
    • Basics of Strings
    • String Special Operators
    • String Formatting Operators
    • String Methods
    • šŸ“ Assignments
  • Regular Expressions
  • Python OOPS
    • Basics of Object Oriented
    • What are Classes and Objects?
    • Creating Class and Object
    • OOP vs Procedural Programming
    • Difference Between Classes and Objects
    • Constructors
    • Destructor
    • Built Class Methods and Attributes
    • Class and Instance Variables
    • Inheritance in Python
    • Single Inheritance
    • Multiple Inheritance
    • Multilevel Inheritance
    • Hierarchical Inheritance
    • Hybrid Inheritance
    • Abstraction
    • Method Overriding
    • Abstract Method
    • Interfaces in Python
    • Abstract Class vs Interface
    • Public, Private and Protected
    • Overloading vs Overriding
    • Inheritance vs Composition
    • Encapsulation
    • Polymorphism
    • Inner Classes
    • šŸ“ Assignments
  • Advanced Python
    • Iterator in Python
    • Generator in Python
    • Decorator in Python
    • Type Hints in Python
    • Async/Await Programming
    • Dataclasses in Python
    • Context Managers in Python
    • Property Decorator in Python
    • __slots__ in Python
    • Enums in Python
    • Walrus Operator in Python
    • Match-Case in Python
    • šŸ“ Assignments
  • Python Standard Library
    • Collections Module
    • Itertools Module
    • Functools Module
    • Datetime Module
    • JSON Module
    • OS Module
    • Sys Module
    • Random Module
    • Math Module
    • šŸ“ Assignments
  • Python Testing
    • Unit Testing in Python
    • Pytest Framework
    • Mocking in Python
    • šŸ“ Assignments
  • Python Best Practices
    • PEP 8 Style Guide
    • Docstrings in Python
    • Logging in Python
    • Code Optimization Tips
    • Debugging Techniques
    • šŸ“ Assignments
  • MySQL Database in Python
    • Introduction to MySQL with Python
    • DBMS vs File System
    • Connecting to MySQL Database
    • Create Database in MySQL
    • Create Table in MySQL
    • Insert Data in MySQL
    • Insert Multiple Rows
    • Select Data from MySQL
    • WHERE Clause in MySQL
    • Update Data in MySQL
    • Delete Data from MySQL
    • Parameterized Queries
    • Transaction Management
    • Error Handling
    • Connection Pooling
    • MySQL Drivers Guide
    • Joins in MySQL
    • Aggregation Functions
    • Backup MySQL Database
    • Best Practices
    • šŸ“ Assignments
  • MySQL Database Operations
    • SELECT Statement
    • MySQL Operators
    • DDL Statements
    • DML Statements
    • Subqueries
    • JOIN Operations
    • Aggregation
    • Case Study
    • šŸ“ Assignments
  • Graphics in Python
  • Threads in Python
    • Introduction to Threads
    • Process vs Threads
    • Concurrent Programming & GIL
    • Uses of Threads
    • Creating Threads
    • Single Tasking
    • Multi Tasking
    • Thread Synchronization
    • šŸ“ Assignments
  • Interview Questions & Answers
  • Python Case Studies
  • Multiple Choice Questions
  • šŸ“ Practice Problems
Get in Touch
  • tech2dsm@gmail.com

© Sankalan Data Tech

Python Language Interactive Tutorial

Python: Abstraction

Python Abstraction - Complete Guide

Learn how to hide complex implementation details in Python.

Created by Sankalan Data Tech Team Verified
Data Engineers, Analysts, Scientists & Trainers
Created by experienced Python developers, data engineers, and data scientists to make programming easy through practical examples, real-world experience, and clear explanations.
On this page:
  • What is Abstraction?
  • Why Do We Need Abstraction?
  • Abstract Classes in Python
  • Abstract Methods
  • Concrete Classes
  • Real-World Examples
  • Best Practices
  • Try It Yourself
  • Quick Quiz
  • Frequently Asked Questions
Share this tutorial:
Twitter LinkedIn Facebook WhatsApp Reddit Telegram Email Copy Link
What You'll Learn Here
  • What is abstraction — hiding complex details and showing only what's needed
  • Why we need abstraction — making code simpler and easier to use
  • Abstract classes — classes that can't be instantiated directly
  • Abstract methods — methods that must be implemented by child classes
  • Concrete classes — classes that implement all abstract methods
  • Real-world use — practical examples you can use

What is Abstraction?

Abstraction is one of the four pillars of Object-Oriented Programming (along with Encapsulation, Inheritance, and Polymorphism). It means hiding complex implementation details and showing only the essential features of an object.

Think of a car. When you drive a car, you don't need to know how the engine works, how the fuel injection system operates, or how the transmission shifts gears. You just need to know how to use the steering wheel, pedals, and gear shift. The complex details are abstracted away from you.

In Python, abstraction is achieved through abstract classes and abstract methods. An abstract class is like a blueprint — it defines what methods a class should have, but doesn't provide the implementation. Child classes then provide the actual implementation.

šŸ’” Key concept: Abstraction is about showing only what's necessary and hiding what's not. It makes your code cleaner, easier to understand, and easier to maintain.

Why Do We Need Abstraction?

1

Making Complex Things Simple

Abstraction helps us manage complexity. When you build a large system, things get complicated quickly. Abstraction allows you to break down the system into smaller, manageable pieces. Each piece has a clear purpose and hides its internal workings.

# Without abstraction — everything is exposed

class CoffeeMachine:
    def __init__(self):
        self.water_level = 1000  # ml
        self.coffee_beans = 500  # grams
        self.milk = 500  # ml
        self.boiler_temp = 0
        self.pump_pressure = 0
        self.grinder_speed = 0
    
    def grind_beans(self, amount):
        self.grinder_speed = 200
        return f"Grinding {amount}g of beans"
    
    def heat_water(self, temp):
        self.boiler_temp = temp
        return f"Heating water to {temp}°C"
    
    def pump_water(self):
        self.pump_pressure = 9
        return "Pumping water through coffee"
    
    def steam_milk(self):
        return "Steaming milk"
    
    # The user needs to know ALL of this to make coffee!
    def make_espresso(self):
        self.grind_beans(18)
        self.heat_water(92)
        self.pump_water()
        return "ā˜• Espresso ready!"
    
    def make_latte(self):
        self.grind_beans(20)
        self.heat_water(90)
        self.pump_water()
        self.steam_milk()
        return "ā˜• Latte ready!"

# The user still sees too many details!
machine = CoffeeMachine()
print(machine.make_espresso())
print(machine.water_level)  # User can see internal details

# With abstraction — only what's needed is shown
from abc import ABC, abstractmethod

class CoffeeMachine(ABC):
    """Abstract class — defines what a coffee machine can do"""
    
    def __init__(self):
        self._water_level = 1000  # Private — hidden from user
        self._coffee_beans = 500  # Private — hidden from user
    
    @abstractmethod
    def make_coffee(self, coffee_type):
        """Abstract method — child classes must implement this"""
        pass
    
    @abstractmethod
    def get_status(self):
        """Abstract method — returns machine status"""
        pass

class EspressoMachine(CoffeeMachine):
    """Concrete class — implements the abstract methods"""
    
    def __init__(self):
        super().__init__()
        self._steam_pressure = 9
    
    def make_coffee(self, coffee_type):
        # All the complex details are hidden inside this method
        if coffee_type == "espresso":
            return "ā˜• Making a perfect espresso with 9 bar pressure"
        elif coffee_type == "latte":
            return "ā˜• Making a creamy latte with steamed milk"
        else:
            return "I can only make espresso and latte"
    
    def get_status(self):
        return f"Water: {self._water_level}ml, Beans: {self._coffee_beans}g"

# User only sees what they need!
machine = EspressoMachine()
print(machine.make_coffee("espresso"))  # Simple! Just call the method
print(machine.get_status())             # Simple status check
# machine._water_level  # Can't access — hidden and protected!

Why abstraction matters:

  • Hides complexity — users don't need to know internal details
  • Reduces errors — users can't accidentally break internal parts
  • Makes code reusable — different implementations can share the same interface
  • Easier maintenance — you can change internals without affecting users
  • Clearer design — each class has a clear purpose

Quick Check: What is abstraction in programming? (Answer: Hiding complex implementation details and showing only what's needed)

Abstract Classes in Python

2

What is an Abstract Class?

An abstract class is a class that you can't create objects from. It's designed to be a base class for other classes. It defines a blueprint — it tells child classes what methods they must implement.

In Python, you create abstract classes using the abc module (ABC = Abstract Base Class). You inherit from ABC and use the @abstractmethod decorator.

# Creating abstract classes in Python

from abc import ABC, abstractmethod

# 1. Basic abstract class
class Shape(ABC):
    """Abstract class — defines what a shape should do"""
    
    @abstractmethod
    def area(self):
        """Calculate the area of the shape"""
        pass
    
    @abstractmethod
    def perimeter(self):
        """Calculate the perimeter of the shape"""
        pass
    
    def info(self):
        """Concrete method — all child classes inherit this"""
        return f"This is a shape"

# Creating a child class that implements all abstract methods
class Rectangle(Shape):
    """Concrete class — implements all abstract methods"""
    
    def __init__(self, width, height):
        self.width = width
        self.height = height
    
    def area(self):
        return self.width * self.height
    
    def perimeter(self):
        return 2 * (self.width + self.height)

class Circle(Shape):
    """Concrete class — implements all abstract methods"""
    
    def __init__(self, radius):
        self.radius = radius
    
    def area(self):
        return 3.14 * self.radius * self.radius
    
    def perimeter(self):
        return 2 * 3.14 * self.radius

# Using the classes
rect = Rectangle(5, 3)
circle = Circle(4)

print(f"Rectangle area: {rect.area()}")
print(f"Rectangle perimeter: {rect.perimeter()}")
print(f"Circle area: {circle.area():.2f}")
print(f"Circle perimeter: {circle.perimeter():.2f}")

# Both are shapes, but each works differently
print(rect.info())
print(circle.info())

# You CANNOT create an abstract class directly
# shape = Shape()  # This would raise TypeError!

print("\nAbstract class is a blueprint — you can't use it directly!")
print("You must create concrete child classes that implement all abstract methods")

Abstract class key points:

  • Can't be instantiated — you can't create an object from it
  • Blueprint for other classes — defines what child classes must do
  • Can have abstract methods — methods without implementation
  • Can have concrete methods — methods with implementation that children inherit
  • Child must implement all abstract methods — or it remains abstract

Quick Check: Can you create an object from an abstract class? (Answer: No, you can't — it must be inherited by a concrete class)

Abstract Methods

3

Methods That Must Be Implemented

An abstract method is a method that's declared in an abstract class but has no implementation. It's like a promise — "I'm telling you that this method exists, but you must provide the actual code."

Any child class that inherits from the abstract class must implement all abstract methods. If it doesn't, it will also be abstract and can't be instantiated.

# Abstract methods in action

from abc import ABC, abstractmethod

class Payment(ABC):
    """Abstract class — defines payment interface"""
    
    @abstractmethod
    def process_payment(self, amount):
        """Process a payment — must be implemented"""
        pass
    
    @abstractmethod
    def refund(self, transaction_id):
        """Refund a payment — must be implemented"""
        pass
    
    @abstractmethod
    def get_status(self, transaction_id):
        """Get payment status — must be implemented"""
        pass
    
    def log_transaction(self, message):
        """Concrete method — all payment methods can use this"""
        print(f"[LOG] {message}")
        return "Transaction logged"

# Child class 1 — implements all abstract methods
class CreditCardPayment(Payment):
    def process_payment(self, amount):
        self.log_transaction(f"Processing credit card: ${amount}")
        return f"Credit card payment of ${amount} processed"
    
    def refund(self, transaction_id):
        self.log_transaction(f"Refunding: {transaction_id}")
        return f"Refund processed for {transaction_id}"
    
    def get_status(self, transaction_id):
        return f"Status of {transaction_id}: Completed"

# Child class 2 — implements all abstract methods
class PayPalPayment(Payment):
    def process_payment(self, amount):
        self.log_transaction(f"Processing PayPal: ${amount}")
        return f"PayPal payment of ${amount} processed"
    
    def refund(self, transaction_id):
        self.log_transaction(f"Refunding PayPal: {transaction_id}")
        return f"PayPal refund processed for {transaction_id}"
    
    def get_status(self, transaction_id):
        return f"Status of {transaction_id}: In Progress"

# This would cause an error — missing implementation
# class CryptoPayment(Payment):
#     def process_payment(self, amount):
#         return "Crypto payment processed"
#     # Missing refund() and get_status() → Error!

# Using the classes
print("=== CREDIT CARD ===")
cc = CreditCardPayment()
print(cc.process_payment(100.50))
print(cc.get_status("TXN001"))
print(cc.refund("TXN001"))

print("\n=== PAYPAL ===")
pp = PayPalPayment()
print(pp.process_payment(75.25))
print(pp.get_status("TXN002"))
print(pp.refund("TXN002"))

print("\nAll abstract methods must be implemented in child classes!")
print("This ensures consistency across all payment methods.")

Abstract methods key points:

  • No implementation — only the method signature is defined
  • Must be implemented — child classes must provide the code
  • Enforces consistency — all child classes have the same methods
  • Uses @abstractmethod — decorator from the abc module
  • Can have docstrings — describes what the method should do

Quick Check: What happens if a child class doesn't implement all abstract methods? (Answer: The child class will also be abstract and can't be instantiated)

Concrete Classes

4

Implementing the Blueprint

A concrete class is a class that implements all abstract methods from its parent abstract class. It's called "concrete" because it provides actual implementation — you can create objects from it.

Think of an abstract class as a job description, and concrete classes as the people who fill those jobs. Each person does the job in their own way, but they all follow the same description.

# Concrete classes — implementing the blueprint

from abc import ABC, abstractmethod

# Abstract class (job description)
class Vehicle(ABC):
    """Abstract class — defines what a vehicle can do"""
    
    @abstractmethod
    def start(self):
        """Start the vehicle — must be implemented"""
        pass
    
    @abstractmethod
    def stop(self):
        """Stop the vehicle — must be implemented"""
        pass
    
    @abstractmethod
    def fuel(self):
        """Fuel the vehicle — must be implemented"""
        pass
    
    def get_info(self):
        """Concrete method — all vehicles share this"""
        return "This is a vehicle"

# Concrete class 1 — Car
class Car(Vehicle):
    def __init__(self, brand, model):
        self.brand = brand
        self.model = model
        self.is_running = False
    
    def start(self):
        self.is_running = True
        return f"{self.brand} {self.model} engine started"
    
    def stop(self):
        self.is_running = False
        return f"{self.brand} {self.model} engine stopped"
    
    def fuel(self):
        return f"Filling {self.brand} {self.model} with petrol"
    
    # Car-specific method
    def honk(self):
        return f"{self.brand} {self.model} says Beep Beep!"

# Concrete class 2 — ElectricCar
class ElectricCar(Vehicle):
    def __init__(self, brand, model, battery_capacity):
        self.brand = brand
        self.model = model
        self.battery_capacity = battery_capacity
        self.is_charging = False
    
    def start(self):
        return f"{self.brand} {self.model} powered up silently"
    
    def stop(self):
        return f"{self.brand} {self.model} powered down"
    
    def fuel(self):
        self.is_charging = True
        return f"Charging {self.brand} {self.model} with {self.battery_capacity} kWh"
    
    # ElectricCar-specific method
    def check_battery(self):
        return f"{self.brand} {self.model} has {self.battery_capacity} kWh battery"

# Concrete class 3 — Bicycle
class Bicycle(Vehicle):
    def __init__(self, brand, type_):
        self.brand = brand
        self.type_ = type_
    
    def start(self):
        return f"Starting to pedal the {self.brand} {self.type_} bike"
    
    def stop(self):
        return f"Stopping the {self.brand} {self.type_} bike"
    
    def fuel(self):
        return "Fueled by human power! 🚓"
    
    # Bicycle-specific method
    def ring_bell(self):
        return f"{self.brand} bike says Ring Ring!"

# Using concrete classes
print("=== CAR ===")
car = Car("Toyota", "Camry")
print(car.start())
print(car.honk())
print(car.fuel())
print(car.stop())
print(car.get_info())

print("\n=== ELECTRIC CAR ===")
ev = ElectricCar("Tesla", "Model 3", 75)
print(ev.start())
print(ev.fuel())
print(ev.check_battery())
print(ev.stop())

print("\n=== BICYCLE ===")
bike = Bicycle("Giant", "Mountain")
print(bike.start())
print(bike.fuel())
print(bike.ring_bell())
print(bike.stop())

print("\nAll concrete classes implement the same abstract methods,")
print("but each does it in its own unique way!")

Concrete class key points:

  • Implements all abstract methods — provides actual code
  • Can be instantiated — you can create objects from it
  • Can have its own methods — specific to that class
  • Follows the blueprint — must match the abstract class interface
  • Each is unique — different concrete classes can implement methods differently

Quick Check: What makes a class a "concrete" class? (Answer: It implements all abstract methods from its parent abstract class)

Real-World Examples

5

Seeing Abstraction in Action

# Real-world example: A Database System

from abc import ABC, abstractmethod

# Abstract class — defines database interface
class Database(ABC):
    """Abstract class — defines how to work with a database"""
    
    @abstractmethod
    def connect(self):
        """Connect to the database"""
        pass
    
    @abstractmethod
    def disconnect(self):
        """Disconnect from the database"""
        pass
    
    @abstractmethod
    def execute_query(self, query):
        """Execute a SQL query"""
        pass
    
    @abstractmethod
    def insert(self, table, data):
        """Insert data into a table"""
        pass
    
    @abstractmethod
    def select(self, table, columns="*", condition=None):
        """Select data from a table"""
        pass
    
    def backup(self):
        """Concrete method — common for all databases"""
        return "Database backup completed"

# Concrete class 1 — MySQL Database
class MySQLDatabase(Database):
    def __init__(self, host, user, password):
        self.host = host
        self.user = user
        self.password = password
        self.connected = False
    
    def connect(self):
        self.connected = True
        return f"Connected to MySQL at {self.host} as {self.user}"
    
    def disconnect(self):
        self.connected = False
        return "Disconnected from MySQL"
    
    def execute_query(self, query):
        if not self.connected:
            return "Error: Not connected to MySQL"
        return f"MySQL: Executing '{query}'"
    
    def insert(self, table, data):
        return f"MySQL: Inserting {data} into {table}"
    
    def select(self, table, columns="*", condition=None):
        where = f" WHERE {condition}" if condition else ""
        return f"MySQL: SELECT {columns} FROM {table}{where}"

# Concrete class 2 — PostgreSQL Database
class PostgreSQLDatabase(Database):
    def __init__(self, host, database, user):
        self.host = host
        self.database = database
        self.user = user
        self.connected = False
    
    def connect(self):
        self.connected = True
        return f"Connected to PostgreSQL at {self.host}/{self.database}"
    
    def disconnect(self):
        self.connected = False
        return "Disconnected from PostgreSQL"
    
    def execute_query(self, query):
        if not self.connected:
            return "Error: Not connected to PostgreSQL"
        return f"PostgreSQL: Executing '{query}'"
    
    def insert(self, table, data):
        return f"PostgreSQL: Inserting {data} into {table}"
    
    def select(self, table, columns="*", condition=None):
        where = f" WHERE {condition}" if condition else ""
        return f"PostgreSQL: SELECT {columns} FROM {table}{where}"

# Concrete class 3 — SQLite Database
class SQLiteDatabase(Database):
    def __init__(self, file_path):
        self.file_path = file_path
        self.connected = False
    
    def connect(self):
        self.connected = True
        return f"Connected to SQLite at {self.file_path}"
    
    def disconnect(self):
        self.connected = False
        return "Disconnected from SQLite"
    
    def execute_query(self, query):
        if not self.connected:
            return "Error: Not connected to SQLite"
        return f"SQLite: Executing '{query}'"
    
    def insert(self, table, data):
        return f"SQLite: Inserting {data} into {table}"
    
    def select(self, table, columns="*", condition=None):
        where = f" WHERE {condition}" if condition else ""
        return f"SQLite: SELECT {columns} FROM {table}{where}"

# Using the databases (abstraction in action)
print("=" * 50)
print("DATABASE SYSTEM WITH ABSTRACTION")
print("=" * 50)

def database_manager(db):
    """Function that works with any database (polymorphism)"""
    print(db.connect())
    print(db.insert("users", {"name": "Alice", "age": 30}))
    print(db.select("users", condition="age > 25"))
    print(db.execute_query("DELETE FROM users WHERE age < 18"))
    print(db.disconnect())

print("\n=== MYSQL ===")
mysql = MySQLDatabase("localhost", "root", "pass123")
database_manager(mysql)

print("\n=== POSTGRESQL ===")
pg = PostgreSQLDatabase("localhost", "app_db", "admin")
database_manager(pg)

print("\n=== SQLITE ===")
sqlite = SQLiteDatabase("/tmp/app.db")
database_manager(sqlite)

print("\nāœ… Abstraction allows us to work with different databases using the same interface!")
print("The database manager function works with ANY database class.")

Real-world example key points:

  • Abstract class — Database defines the interface (connect, disconnect, execute_query, insert, select)
  • Concrete classes — MySQLDatabase, PostgreSQLDatabase, SQLiteDatabase each implement the methods differently
  • Abstraction in action — database_manager() works with ANY database type
  • No code duplication — each database has its own implementation
  • Easy to add new databases — just create a new class that implements Database

Quick Check: In the database example, what does the database_manager function demonstrate? (Answer: Polymorphism — it works with any database class that inherits from Database)

Best Practices for Abstraction

6

Using Abstraction Effectively

# Best practices for abstraction

from abc import ABC, abstractmethod

# 1. Keep abstract classes focused
#  Good — one clear purpose
class Logger(ABC):
    @abstractmethod
    def log(self, message):
        pass

class FileLogger(Logger):
    def log(self, message):
        with open("log.txt", "a") as f:
            f.write(message + "\n")

#  Bad — too many unrelated methods
class Utility(ABC):
    @abstractmethod
    def log(self, message):
        pass
    @abstractmethod
    def format_data(self, data):
        pass
    @abstractmethod
    def send_email(self, to, subject):
        pass  # These are unrelated!

# 2. Use abstract methods to enforce contracts
class Shape(ABC):
    @abstractmethod
    def area(self):
        """Must be implemented by all shapes"""
        pass

class Circle(Shape):
    def __init__(self, radius):
        self.radius = radius
    
    def area(self):
        return 3.14 * self.radius ** 2

# 3. Provide concrete methods when useful
class Animal(ABC):
    @abstractmethod
    def sound(self):
        pass
    
    def breathe(self):
        return "Breathing..."  # All animals breathe the same way

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

# 4. Use docstrings to document abstract methods
class PaymentProcessor(ABC):
    @abstractmethod
    def process(self, amount):
        """
        Process a payment of the given amount.
        
        Args:
            amount (float): The amount to process
            
        Returns:
            str: Status message
        """
        pass

# 5. Don't overuse abstraction
#  Good — used when needed
class Report(ABC):
    @abstractmethod
    def generate(self):
        pass

#  Bad — abstract for no reason
class SimpleClass(ABC):
    @abstractmethod
    def get_value(self):
        pass  # Overkill for something simple

# 6. Use abstract classes to define interfaces
class DataSource(ABC):
    @abstractmethod
    def get_data(self):
        pass
    
    @abstractmethod
    def save_data(self, data):
        pass

# 7. Name abstract classes clearly
#  Good — clearly abstract
class Database(ABC):
    pass

class Repository(ABC):
    pass

#  Bad — confusing names
class DB(ABC):
    pass  # What is this?

# 8. Test with abstract classes
class Testable(ABC):
    @abstractmethod
    def run_test(self):
        pass

class MyClass(Testable):
    def run_test(self):
        print("Test passed!")

# Testing
obj = MyClass()
obj.run_test()  # Works!

Best practices summary:

  • Keep it focused — abstract classes should have a clear, single purpose
  • Enforce contracts — abstract methods ensure child classes do what they should
  • Provide concrete methods — when all children share behavior
  • Document well — abstract methods should have good docstrings
  • Don't overuse — not everything needs to be abstract
  • Define interfaces — abstract classes are perfect for this
  • Use clear names — make it obvious that a class is abstract
  • Test your classes — make sure child classes work correctly

Quick Check: What's a good reason to use abstraction? (Answer: To define a clear interface that multiple implementations must follow)

Try It Yourself

Experiment with abstraction in the editor below.

Loading Pyodide... 0%
Python Code Editor
========================================
ABSTRACTION PRACTICE
========================================

1. CREATING AN ABSTRACT CLASS

2. CREATING CONCRETE CLASSES

3. USING THE CLASSES
LG washing machine started
Added 5kg of clothes
LG: ON, Load: 5kg
LG washing machine stopped
Samsung refrigerator started cooling
Temperature set to 2°C
Samsung: ON, Temp: 2°C
Samsung refrigerator stopped

4. ABSTRACTION IN ACTION
Both classes implement the same interface:
- turn_on()
- turn_off()
- get_status()
But each does it differently!

Abstraction practice complete!
šŸ†

You've Got It!

You now understand abstraction in Python. You know how to create abstract classes, define abstract methods, and implement concrete classes that follow the blueprint.

Quick Quiz

Test what you've learned:

1. What is abstraction in Python?
2. Can you create an object from an abstract class?
3. What decorator is used to define an abstract method?
4. What must a concrete class do?
5. What module is needed to create abstract classes in Python?

Frequently Asked Questions

What's the difference between abstraction and encapsulation? ā–¼

Abstraction is about hiding implementation details and showing only what's needed — it's about the interface. Encapsulation is about bundling data and methods together and protecting internal state — it's about access control. Abstraction says "what you need to know," encapsulation says "what you can access."

Can an abstract class have concrete methods? ā–¼

Yes! Abstract classes can have both abstract and concrete methods. Concrete methods are fully implemented in the abstract class and are inherited by child classes. This is useful for providing common functionality that all children can use.

What happens if a child class doesn't implement all abstract methods? ā–¼

If a child class doesn't implement all abstract methods, it will also be an abstract class. You won't be able to create objects from it. Python will raise a TypeError when you try to instantiate it. The child class must implement all abstract methods to become concrete.

Why use abstraction instead of just regular classes? ā–¼

Abstraction enforces a contract — it guarantees that all child classes have certain methods. This makes your code more predictable and easier to work with. It also helps with polymorphism — you can write code that works with any child class, knowing it has the required methods.

What's a common interview question about abstraction? ā–¼

Common questions include: "What is abstraction and why is it important?" "Explain the difference between abstraction and encapsulation." "How do you create an abstract class in Python?" and "What is the purpose of the @abstractmethod decorator?"

When should I use abstraction? ā–¼

Use abstraction when you have a clear interface that multiple classes should follow. Examples include: database connectors (MySQL, PostgreSQL, SQLite), payment processors (Credit Card, PayPal, Crypto), or shapes (Circle, Rectangle, Triangle). It ensures consistency and makes your code more maintainable.

Where to Go From Here

Now that you understand abstraction, check out these related topics:

Abstract Methods

Learn more about abstract methods in detail.

Learn More →

Abstract Class vs Interface

Learn the differences between abstract classes and interfaces.

Learn More →

Interfaces in Python

Learn about implementing interfaces in Python.

Learn More →
Interview Resources
  • Python Syntax & Variables Interview Questions
  • Top SQL Interview Questions & Answers
  • SQL Joins: Displaying Data from Multiple Tables FAQ
  • Python Lists and Dictionaries Interview Questions
  • Python OOP Interview Questions
  • SQL Set Operators Interview Questions
Previous: Hybrid Inheritance Next: Method Overriding →