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