30-July 2024
Training

Solid Principles Python

..
Solid Principles Python

 

The SOLID principles can also be applied to Python to improve the design and maintainability of your code. Here's a breakdown of each principle with examples in Python:

1. Single Responsibility Principle (SRP)

Definition: A class should have only one reason to change, meaning it should have only one job or responsibility. Example in Python:

class Book:

    def __init__(self, title, author):

        self.title = title

        self.author = author

 

class BookPrinter:

    @staticmethod

    def print(book):

        print(f"{book.title} by {book.author}")

 

book = Book("1984", "George Orwell")

BookPrinter.print(book)

In this example, the Book class is responsible for storing book data, while the BookPrinter class handles printing the book details, adhering to SRP.

2. Open/Closed Principle (OCP)

Definition: Software entities (classes, modules, functions, etc.) should be open for extension but closed for modification. Example in Python:

from abc import ABC, abstractmethod

 

class Shape(ABC):

    @abstractmethod

    def draw(self):

        pass

 

class Circle(Shape):

    def draw(self):

        print("Drawing a Circle")

 

class Square(Shape):

    def draw(self):

        print("Drawing a Square")

 

def draw_shape(shape):

    shape.draw()

 

circle = Circle()

square = Square()

draw_shape(circle)

draw_shape(square)

In this example, new shapes can be added by extending the Shape class without modifying the existing code.

3. Liskov Substitution Principle (LSP)

Definition: Objects of a superclass should be replaceable with objects of a subclass without affecting the correctness of the program. Example in Python:

class Bird:

    def fly(self):

        print("Flying")

 

class Sparrow(Bird):

    pass

 

class Ostrich(Bird):

    def fly(self):

        raise NotImplementedError("Ostriches can't fly")

 

def make_bird_fly(bird):

    bird.fly()

 

sparrow = Sparrow()

ostrich = Ostrich()

 

make_bird_fly(sparrow)  # Works fine

make_bird_fly(ostrich)  # Raises error, violates LSP

To adhere to LSP, you might need to redesign the hierarchy:

class Bird:

    pass

 

class FlyingBird(Bird):

    def fly(self):

        print("Flying")

 

class Sparrow(FlyingBird):

    pass

 

class Ostrich(Bird):

    pass

 

def make_bird_fly(bird):

    if isinstance(bird, FlyingBird):

        bird.fly()

 

sparrow = Sparrow()

ostrich = Ostrich()

 

make_bird_fly(sparrow)  # Works fine

make_bird_fly(ostrich)  # Does nothing, adheres to LSP

4. Interface Segregation Principle (ISP)

Definition: Clients should not be forced to depend on interfaces they do not use. Example in Python:

class Worker:

    def work(self):

        pass

 

    def eat(self):

        pass

 

class HumanWorker(Worker):

    def work(self):

        print("Working")

 

    def eat(self):

        print("Eating")

 

class Robot(Worker):

    def work(self):

        print("Working")

 

    def eat(self):

        raise NotImplementedError("Robots do not eat"# Violates ISP

To adhere to ISP:

class Workable:

    def work(self):

        pass

 

class Eatable:

    def eat(self):

        pass

 

class HumanWorker(Workable, Eatable):

    def work(self):

        print("Working")

 

    def eat(self):

        print("Eating")

 

class Robot(Workable):

    def work(self):

        print("Working")

5. Dependency Inversion Principle (DIP)

Definition: High-level modules should not depend on low-level modules. Both should depend on abstractions (e.g., interfaces). Abstractions should not depend on details. Details should depend on abstractions. Example in Python:

class Light:

    def turn_on(self):

        print("Light is on")

 

    def turn_off(self):

        print("Light is off")

 

class Switch:

    def __init__(self, light):

        self.light = light

 

    def operate(self):

        self.light.turn_on()

To adhere to DIP:

class Switchable:

    def turn_on(self):

        pass

 

    def turn_off(self):

        pass

 

class Light(Switchable):

    def turn_on(self):

        print("Light is on")

 

    def turn_off(self):

        print("Light is off")

 

class Switch:

    def __init__(self, device: Switchable):

        self.device = device

 

    def operate(self):

        self.device.turn_on()

By applying these principles in Python, you can create a system that is easier to maintain and extend, leading to better code quality and more robust applications.

 

Leave a comment

Your email address will not be published. Required fields are marked *