0% found this document useful (0 votes)
11 views25 pages

Python Abstraction and Interfaces Guide

The document explains abstraction and interfaces in Python, highlighting their importance in Object-Oriented Programming (OOP). It covers the definition of abstraction, levels of abstraction, abstract classes, and the abc module, along with examples of implementing abstract and concrete methods. Additionally, it discusses interfaces, their characteristics, and how they differ from abstract classes.

Uploaded by

kdas12560
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
11 views25 pages

Python Abstraction and Interfaces Guide

The document explains abstraction and interfaces in Python, highlighting their importance in Object-Oriented Programming (OOP). It covers the definition of abstraction, levels of abstraction, abstract classes, and the abc module, along with examples of implementing abstract and concrete methods. Additionally, it discusses interfaces, their characteristics, and how they differ from abstract classes.

Uploaded by

kdas12560
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd

Abstraction and Interfaces in Python

1. Introduction to Abstraction

What is Abstraction?
Abstraction is one of the four fundamental principles of Object-Oriented Programming (OOP), along with

Encapsulation, Inheritance, and Polymorphism.

Simple Definition: Abstraction means hiding the complex implementation details and showing only the

essential features of an object. It focuses on “what an object does” rather than “how it does it.”

Real-World Analogy
Think about driving a car:

What you see (Abstract): Steering wheel, pedals, gear shift


What you don’t see (Hidden): Engine mechanics, fuel injection system, transmission details

You know what each control does (steering wheel turns the car), but you don’t need to know how it works
internally (hydraulic systems, power steering mechanisms). That’s abstraction!

Another example - Your TV remote:

Abstract: Power button, volume buttons, channel buttons

Hidden: Infrared signals, circuit boards, signal processing

Why is Abstraction Important?

1. Simplifies Complexity - Users don’t need to understand complex internal workings

2. Increases Security - Hides sensitive implementation details


3. Reduces Code Duplication - Common interfaces for similar operations

4. Improves Maintainability - Implementation can change without affecting users

5. Provides Clear Structure - Defines what must be implemented


6. Enables Polymorphism - Different classes can implement the same interface
2. Understanding Abstraction in OOP

Levels of Abstraction
In programming, abstraction exists at multiple levels:

Level 1: Simple Functions

# User sees: Simple function call

result = calculate_average(numbers)

# Hidden: Complex implementation details


def calculate_average(numbers):
total = sum(numbers)

count = len(numbers)
return total / count if count > 0 else 0

Level 2: Classes

# User sees: Simple methods


account = BankAccount()
[Link](100)

[Link](50)

# Hidden: Internal balance management, validation, logging, etc.

Level 3: Abstract Classes and Interfaces

# User sees: What methods must exist

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

# Hidden: Each vehicle implements start differently


Two Types of Abstraction
1. Data Abstraction
Hiding internal data and providing access through methods.

class BankAccount:
def __init__(self):

self.__balance = 0 # Hidden (private)

# Public interface

def deposit(self, amount):


self.__balance += amount

def get_balance(self):
return self.__balance

# Users interact through methods, not directly with __balance

2. Process Abstraction
Hiding implementation details of operations.

class EmailSender:

def send_email(self, to, subject, body):


# Complex implementation hidden

self._connect_to_server()

self._authenticate()
self._compose_message(to, subject, body)

self._send()

self._disconnect()

# Users only call send_email(), details are hidden

3. Abstract Classes in Python


What is an Abstract Class?
Abstract Class is a class that cannot be instantiated (you cannot create objects from it) and is designed to be

inherited by other classes. It serves as a blueprint or template for other classes.

Key Characteristics:

1. Cannot create instances directly

2. Contains one or more abstract methods


3. May also contain concrete (regular) methods

4. Must be inherited by child classes

5. Child classes must implement all abstract methods

Why Use Abstract Classes?

1. Define a Contract - Specify what methods child classes must implement

2. Enforce Standards - Ensure all child classes have required methods


3. Share Common Code - Provide common functionality in concrete methods

4. Prevent Instantiation - Force users to use specific implementations

5. Design Framework - Create frameworks where others fill in the details

Abstract Class vs Regular Class


# Regular Class - Can be instantiated
class Animal:

def speak(self):

print("Some sound")

animal = Animal() # This works fine

# Abstract Class - Cannot be instantiated

from abc import ABC, abstractmethod

class Animal(ABC):

@abstractmethod
def speak(self):

pass
# animal = Animal() # This will raise TypeError!

4. The abc Module (Abstract Base Classes)

What is the abc Module?


The abc module (Abstract Base Classes) is Python’s built-in module for creating abstract classes. It provides
the infrastructure for defining abstract base classes.

ABC stands for Abstract Base Class.

Key Components of abc Module

1. ABC Class - Base class for creating abstract classes


2. abstractmethod Decorator - Marks methods as abstract

3. abstractproperty - For abstract properties (less common)

Importing the abc Module


from abc import ABC, abstractmethod

# Now you can create abstract classes

class MyAbstractClass(ABC):

@abstractmethod
def my_abstract_method(self):

pass

Two Ways to Create Abstract Classes


Method 1: Inherit from ABC (Recommended)
from abc import ABC, abstractmethod

class Shape(ABC):

@abstractmethod
def area(self):
pass

Method 2: Using ABCMeta as Metaclass


from abc import ABCMeta, abstractmethod

class Shape(metaclass=ABCMeta):

@abstractmethod
def area(self):
pass

Both methods work the same way. Method 1 is more common and easier to read.

5. Creating Abstract Classes

Basic Structure
from abc import ABC, abstractmethod

class AbstractClassName(ABC):

@abstractmethod
def abstract_method_name(self):
"""This method must be implemented by child classes"""

pass

def concrete_method(self):

"""This method has implementation and is inherited"""


print("This is a concrete method")

Example 1: Simple Abstract Class


from abc import ABC, abstractmethod

# Abstract class
class Animal(ABC):

def __init__(self, name):


[Link] = name

# Abstract method - must be implemented by child classes


@abstractmethod
def speak(self):

pass

# Concrete method - inherited by all child classes

def introduce(self):
print(f"I am {[Link]}")

# This will raise an error


# animal = Animal("Generic") # TypeError: Can't instantiate abstract class

# Child class must implement abstract methods


class Dog(Animal):
def speak(self):

return "Woof! Woof!"

class Cat(Animal):

def speak(self):
return "Meow! Meow!"

# Now we can create instances of child classes


dog = Dog("Buddy")
cat = Cat("Whiskers")

print("=== Dog ===")


[Link]() # Inherited from Animal

print([Link]()) # Implemented in Dog

print("\n=== Cat ===")

[Link]() # Inherited from Animal


print([Link]()) # Implemented in Cat
Output:

=== Dog ===


I am Buddy

Woof! Woof!

=== Cat ===

I am Whiskers
Meow! Meow!

Detailed Explanation:

1. Abstract Class Animal :

Inherits from ABC to make it abstract

Has one abstract method: speak()

Has one concrete method: introduce()

Cannot be instantiated directly

2. Abstract Method speak() :

Marked with @abstractmethod decorator

Has no implementation (just pass )

Must be implemented by all child classes

3. Concrete Method introduce() :

Has actual implementation

Inherited by all child classes without modification


Can be used directly

4. Child Classes:

Dog and Cat inherit from Animal

Both must implement speak() method

Both get introduce() for free

Example 2: Abstract Class with Multiple Abstract Methods


from abc import ABC, abstractmethod

# Abstract class for geometric shapes

class Shape(ABC):

def __init__(self, color):

[Link] = color

# Abstract methods - must be implemented

@abstractmethod
def area(self):
"""Calculate and return the area"""

pass

@abstractmethod

def perimeter(self):
"""Calculate and return the perimeter"""
pass

# Concrete method - shared functionality


def display_color(self):

print(f"Color: {[Link]}")

def description(self):

print(f"This is a {[Link]} {self.__class__.__name__}")


print(f"Area: {[Link]():.2f}")
print(f"Perimeter: {[Link]():.2f}")

# Concrete class 1: Rectangle


class Rectangle(Shape):

def __init__(self, color, length, width):


super().__init__(color)
[Link] = length

[Link] = width

def area(self):

return [Link] * [Link]


def perimeter(self):
return 2 * ([Link] + [Link])

# Concrete class 2: Circle


class Circle(Shape):
def __init__(self, color, radius):

super().__init__(color)
[Link] = radius

def area(self):
return 3.14159 * ([Link] ** 2)

def perimeter(self):
return 2 * 3.14159 * [Link]

# Create objects
rectangle = Rectangle("Blue", 5, 3)
circle = Circle("Red", 4)

print("=== Rectangle ===")


[Link]()

print("\n=== Circle ===")


[Link]()

# Demonstrate polymorphism
print("\n=== All Shapes ===")

shapes = [rectangle, circle]


for shape in shapes:
print(f"\n{shape.__class__.__name__}:")

shape.display_color()
print(f"Area: {[Link]():.2f}")

Output:
=== Rectangle ===

This is a Blue Rectangle


Area: 15.00
Perimeter: 16.00

=== Circle ===


This is a Red Circle

Area: 50.27
Perimeter: 25.13

=== All Shapes ===

Rectangle:

Color: Blue
Area: 15.00

Circle:

Color: Red

Area: 50.27

Detailed Explanation:

1. Multiple Abstract Methods:

area() and perimeter() must both be implemented

Child classes cannot skip implementing any abstract method

2. Shared Functionality:

display_color() and description() are concrete methods

All child classes inherit and can use them

Reduces code duplication

3. Polymorphism:

All shapes can be stored in a single list

Can call area() on any shape

Each shape calculates differently


6. Abstract Methods and Concrete Methods

Abstract Methods
Definition: Methods declared in an abstract class but have no implementation. Child classes must provide the
implementation.

Characteristics:

1. Decorated with @abstractmethod

2. Can have just pass or ... or a docstring

3. Cannot be called directly


4. Must be overridden in child classes

from abc import ABC, abstractmethod

class PaymentProcessor(ABC):

@abstractmethod

def process_payment(self, amount):

"""Process payment of given amount"""


pass

@abstractmethod
def refund(self, transaction_id):

"""Refund a transaction"""

...

@abstractmethod

def get_transaction_status(self, transaction_id):


"""

Get status of a transaction.

Returns: 'success', 'pending', or 'failed'


"""

# Abstract methods can have docstrings

pass
Concrete Methods
Definition: Regular methods with complete implementation in the abstract class. Child classes inherit them

as-is.

Characteristics:

1. No @abstractmethod decorator

2. Have full implementation


3. Can be used directly by child classes

4. Can be overridden if needed

from abc import ABC, abstractmethod

class DatabaseConnection(ABC):

def __init__(self, host, port):

[Link] = host
[Link] = port

self.is_connected = False

# Abstract method

@abstractmethod

def connect(self):
pass

# Concrete method
def get_connection_string(self):

return f"{[Link]}:{[Link]}"

# Concrete method

def log_activity(self, message):

print(f"[{self.__class__.__name__}] {message}")

Combining Both Types


from abc import ABC, abstractmethod

class FileHandler(ABC):

def __init__(self, filename):

[Link] = filename
self.is_open = False

# Abstract methods - different for each file type


@abstractmethod

def read(self):

pass

@abstractmethod

def write(self, data):


pass

# Concrete methods - same for all file types


def open_file(self):

self.is_open = True

print(f"Opening {[Link]}")

def close_file(self):

self.is_open = False
print(f"Closing {[Link]}")

def get_filename(self):
return [Link]

# Child class 1: Text files


class TextFileHandler(FileHandler):

def read(self):

if self.is_open:
return f"Reading text from {[Link]}"

return "File not open"

def write(self, data):


if self.is_open:

print(f"Writing text to {[Link]}: {data}")

# Child class 2: Binary files

class BinaryFileHandler(FileHandler):

def read(self):
if self.is_open:

return f"Reading binary data from {[Link]}"

return "File not open"

def write(self, data):

if self.is_open:
print(f"Writing binary data to {[Link]}")

# Using the classes


print("=== Text File ===")

text_file = TextFileHandler("[Link]")

text_file.open_file() # Concrete method


print(text_file.read()) # Abstract method implemented

text_file.write("Hello, World!") # Abstract method implemented

text_file.close_file() # Concrete method

print("\n=== Binary File ===")

binary_file = BinaryFileHandler("[Link]")
binary_file.open_file() # Concrete method

print(binary_file.read()) # Abstract method implemented

binary_file.write(b"binary_data") # Abstract method implemented


binary_file.close_file() # Concrete method

Output:

=== Text File ===

Opening [Link]

Reading text from [Link]


Writing text to [Link]: Hello, World!

Closing [Link]
=== Binary File ===

Opening [Link]

Reading binary data from [Link]


Writing binary data to [Link]

Closing [Link]

Explanation:

Abstract methods ( read() , write() ) are implemented differently in each child class

Concrete methods ( open_file() , close_file() , get_filename() ) work the same for all child

classes

This reduces code duplication while maintaining flexibility

7. Interfaces in Python

What is an Interface?
An Interface is a contract that defines what methods a class must implement, without providing any
implementation. It’s like a blueprint that specifies “what” must be done, not “how” to do it.

Key Characteristics:

1. Contains only method signatures (no implementation)

2. Cannot be instantiated

3. Classes that implement the interface must provide all methods


4. Used to achieve 100% abstraction

Interfaces in Other Languages vs Python


In Java/C#:

Have a dedicated interface keyword

Interfaces cannot have any implementation

In Python:

No separate interface keyword

Interfaces are created using abstract classes with only abstract methods
Sometimes called “Pure Abstract Classes”

Creating Interfaces in Python


from abc import ABC, abstractmethod

# This is an interface (pure abstract class)

class PaymentInterface(ABC):

@abstractmethod

def make_payment(self, amount):


pass

@abstractmethod

def verify_payment(self, transaction_id):

pass

@abstractmethod

def cancel_payment(self, transaction_id):


pass

# No concrete methods - only abstract methods


# This makes it a pure interface

Interface vs Abstract Class


Feature Interface Abstract Class

Methods Only abstract methods Abstract + Concrete methods

Implementation No implementation Can have some implementation

Purpose Define contract Provide base functionality

Abstraction Level 100% abstraction Partial abstraction

Use Case “What” must be done “What” + some “How”

8. Implementing Interfaces
Example 1: Simple Interface Implementation
from abc import ABC, abstractmethod

# Interface definition
class Drawable(ABC):

@abstractmethod
def draw(self):

"""Draw the object"""

pass

@abstractmethod

def resize(self, scale):


"""Resize the object"""

pass

# Class 1 implementing the interface

class Circle(Drawable):

def __init__(self, radius):


[Link] = radius

def draw(self):
print(f"Drawing a circle with radius {[Link]}")

def resize(self, scale):


[Link] *= scale

print(f"Circle resized. New radius: {[Link]}")

# Class 2 implementing the interface

class Rectangle(Drawable):

def __init__(self, width, height):


[Link] = width

[Link] = height

def draw(self):

print(f"Drawing a rectangle {[Link]}x{[Link]}")


def resize(self, scale):
[Link] *= scale

[Link] *= scale

print(f"Rectangle resized. New dimensions: {[Link]}x{[Link]}")

# Class 3 implementing the interface

class Triangle(Drawable):
def __init__(self, base, height):

[Link] = base

[Link] = height

def draw(self):

print(f"Drawing a triangle with base {[Link]} and height {[Link]}")

def resize(self, scale):

[Link] *= scale
[Link] *= scale

print(f"Triangle resized. New dimensions: base={[Link]}, height={[Link]

t}")

# Using the interface - Polymorphism

def render_shape(shape: Drawable):


"""Function accepts any object that implements Drawable interface"""

[Link]()

[Link](1.5)

# Create objects

circle = Circle(5)
rectangle = Rectangle(10, 20)

triangle = Triangle(8, 6)

# All can be treated uniformly because they implement the same interface

shapes = [circle, rectangle, triangle]

print("=== Rendering All Shapes ===")

for shape in shapes:


render_shape(shape)

print()

Output:

=== Rendering All Shapes ===

Drawing a circle with radius 5


Circle resized. New radius: 7.5

Drawing a rectangle 10x20


Rectangle resized. New dimensions: 15.0x30.0

Drawing a triangle with base 8 and height 6


Triangle resized. New dimensions: base=12.0, height=9.0

Detailed Explanation:

1. Interface Drawable :

Defines two methods: draw() and resize()

No implementation, only signatures

Acts as a contract

2. Three Implementations:

Circle, Rectangle, and Triangle all implement Drawable

Each provides its own implementation

All satisfy the interface contract

3. Polymorphism:

render_shape() function accepts any Drawable object

Works with Circle, Rectangle, or Triangle


Doesn’t need to know the specific type

Example 2: Multiple Interfaces


from abc import ABC, abstractmethod

# Interface 1: Playable

class Playable(ABC):

@abstractmethod

def play(self):
pass

@abstractmethod
def pause(self):

pass

@abstractmethod

def stop(self):

pass

# Interface 2: Downloadable

class Downloadable(ABC):

@abstractmethod

def download(self):
pass

@abstractmethod
def get_file_size(self):

pass

# Class implementing both interfaces

class VideoFile(Playable, Downloadable):

def __init__(self, title, duration, file_size_mb):

[Link] = title

[Link] = duration
self.file_size_mb = file_size_mb

self.is_playing = False

# Implementing Playable interface


def play(self):

self.is_playing = True
print(f"Playing video: {[Link]}")

def pause(self):

print(f"Paused: {[Link]}")

def stop(self):
self.is_playing = False

print(f"Stopped: {[Link]}")

# Implementing Downloadable interface

def download(self):

print(f"Downloading {[Link]} ({self.file_size_mb} MB)...")


print("Download complete!")

def get_file_size(self):

return self.file_size_mb

# Class implementing only Playable


class AudioFile(Playable):

def __init__(self, title, artist):

[Link] = title

[Link] = artist

def play(self):
print(f"Playing song: {[Link]} by {[Link]}")

def pause(self):

print(f"Paused: {[Link]}")

def stop(self):
print(f"Stopped: {[Link]}")

# Using the interfaces

video = VideoFile("Python Tutorial", "15:30", 250)

audio = AudioFile("Imagine", "John Lennon")


print("=== Video File (Playable + Downloadable) ===")

[Link]()

[Link]()

[Link]()

print(f"File size: {video.get_file_size()} MB")


[Link]()

print("\n=== Audio File (Playable only) ===")

[Link]()

[Link]()

[Link]()

Output:

=== Video File (Playable + Downloadable) ===


Playing video: Python Tutorial

Paused: Python Tutorial

Stopped: Python Tutorial

File size: 250 MB

Downloading Python Tutorial (250 MB)...

Download complete!

=== Audio File (Playable only) ===

Playing song: Imagine by John Lennon

Paused: Imagine

Stopped: Imagine

Explanation:

VideoFile implements both Playable and Downloadable interfaces

AudioFile implements only Playable interface

Each class must implement all methods from its interfaces

This is multiple interface implementation (similar to multiple inheritance)

Summary
Key Concepts to Remember

1. Abstraction

Hides complex implementation details


Shows only essential features

Achieved through abstract classes and interfaces

2. Abstract Classes

Cannot be instantiated

May contain abstract and concrete methods

Serve as blueprints for child classes


Created using abc module

3. Abstract Methods

Declared with @abstractmethod decorator

Have no implementation in abstract class

Must be implemented by all child classes

Define the contract

4. Interfaces in Python

Pure abstract classes (only abstract methods)

Define what must be done, not how

Achieved using ABC with only abstract methods

Enable polymorphism and flexibility

5. The abc Module

ABC class - base for abstract classes

abstractmethod - decorator for abstract methods

Enforces implementation in child classes

Prevents instantiation of abstract classes

Benefits of Abstraction

1. Simplicity - Complex details hidden

2. Security - Implementation details protected


3. Flexibility - Easy to add new implementations

4. Maintainability - Changes don’t break user code


5. Clear Contracts - Everyone knows what to implement

6. Polymorphism - Work with multiple types uniformly

When to Use

Abstract Classes: When you want to provide some shared implementation along with abstract

methods

Interfaces: When you want to define a pure contract with no implementation

Both: When designing frameworks, plugins, or extensible systems

Best Practices

1. Keep interfaces small and focused

2. Document abstract methods clearly

3. Use type hints for better code clarity

4. Prefer composition over inheritance when possible

5. Follow SOLID principles (especially Interface Segregation)


6. Name abstract classes/interfaces clearly (e.g., Drawable , Payable )

By understanding and properly using abstraction and interfaces, you can write more maintainable, flexible, and
professional Python code that’s easy to extend and modify.

You might also like