Understanding SOLID Principles with Python Examples
The SOLID principles are a set of design principles that help developers create more maintainable and scalable software. Let's break down each principle with brief Python examples.
1. Single Responsibility Principle (SRP)
A class should have only one reason to change, meaning it should have only one job or responsibility.
class Invoice:
def __init__(self, items):
self.items = items
def calculate_total(self):
return sum(item['price'] for item in self.items)
class InvoicePrinter:
def print_invoice(self, invoice):
for item in invoice.items:
print(f"{item['name']}: ${item['price']}")
print(f"Total: ${invoice.calculate_total()}")
# Usage
invoice = Invoice([{'name': 'Book', 'price': 10}, {'name': 'Pen', 'price': 2}])
printer = InvoicePrinter()
printer.print_invoice(invoice)
2. Open/Closed Principle (OCP)
Software entities should be open for extension but closed for modification.
class Discount:
def apply(self, amount):
return amount
class TenPercentDiscount(Discount):
def apply(self, amount):
return amount * 0.9
# Usage
discount = TenPercentDiscount()
print(discount.apply(100)) # Output: 90.0
3. Liskov Substitution Principle (LSP)
Objects of a superclass should be replaceable with objects of a subclass without affecting the correctness of the program.
class Bird:
def fly(self):
return "Flying"
class Sparrow(Bird):
pass
class Ostrich(Bird):
def fly(self):
return "Can't fly"
# Usage
def make_bird_fly(bird: Bird):
print(bird.fly())
sparrow = Sparrow()
ostrich = Ostrich()
make_bird_fly(sparrow) # Output: Flying
make_bird_fly(ostrich) # Output: Can't fly
4. Interface Segregation Principle (ISP)
Clients should not be forced to depend on interfaces they do not use.
class Printer:
def print(self, document):
pass
class Scanner:
def scan(self, document):
pass
class MultiFunctionPrinter(Printer, Scanner):
def print(self, document):
print(f"Printing: {document}")
def scan(self, document):
print(f"Scanning: {document}")
# Usage
mfp = MultiFunctionPrinter()
mfp.print("Document1")
mfp.scan("Document2")
5. Dependency Inversion Principle (DIP)
High-level modules should not depend on low-level modules. Both should depend on abstractions.
class Database:
def connect(self):
pass
class MySQLDatabase(Database):
def connect(self):
print("Connecting to MySQL")
class Application:
def __init__(self, db: Database):
self.db = db
def start(self):
self.db.connect()
# Usage
db = MySQLDatabase()
app = Application(db)
app.start() # Output: Connecting to MySQL
These examples illustrate the SOLID principles in a concise manner using Python. Each principle helps in building a robust, scalable, and maintainable codebase.
Top comments (0)