Fundamentals 9 min read

Understanding SOLID Principles in Python: A Guide to Object‑Oriented Design

This article explains the five SOLID object‑oriented design principles, illustrates each with Python code examples, discusses their benefits, and offers practical advice for applying them effectively in Python development to build maintainable and scalable software.

php中文网 Courses
php中文网 Courses
php中文网 Courses
Understanding SOLID Principles in Python: A Guide to Object‑Oriented Design

1. Overview of SOLID Principles

SOLID is an acronym for five fundamental object‑oriented design principles introduced by Robert C. Martin: Single Responsibility Principle, Open/Closed Principle, Liskov Substitution Principle, Interface Segregation Principle, and Dependency Inversion Principle. Together they form the foundation for building maintainable and extensible software systems.

2. Single Responsibility Principle (SRP)

Definition: a class should have only one reason to change, i.e., it should perform a single responsibility.

Python example:

# 违反SRP的类
class User:
    def __init__(self, name, email):
        self.name = name
        self.email = email

    def save_to_database(self):
        # 数据库保存逻辑
        pass

    def send_email(self, message):
        # 发送邮件逻辑
        pass

# 遵循SRP的重构
class User:
    def __init__(self, name, email):
        self.name = name
        self.email = email

class UserRepository:
    @staticmethod
    def save(user):
        # 数据库保存逻辑
        pass

class EmailService:
    @staticmethod
    def send_email(user, message):
        # 发送邮件逻辑
        pass

Benefits: improves readability and maintainability, reduces the risk of changes.

3. Open/Closed Principle (OCP)

Definition: software entities (classes, modules, functions, etc.) should be open for extension but closed for modification.

Python example:

# 违反OCP的代码
class Rectangle:
    def __init__(self, width, height):
        self.width = width
        self.height = height

class AreaCalculator:
    @staticmethod
    def calculate(shape):
        if isinstance(shape, Rectangle):
            return shape.width * shape.height
        # 添加新形状时需要修改此方法

# 遵循OCP的重构
from abc import ABC, abstractmethod

class Shape(ABC):
    @abstractmethod
    def area(self):
        pass

class Rectangle(Shape):
    def __init__(self, width, height):
        self.width = width
        self.height = height
    def area(self):
        return self.width * self.height

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

class AreaCalculator:
    @staticmethod
    def calculate(shape):
        return shape.area()

Benefits: system becomes more stable, extensible, and reduces regression testing needs.

4. Liskov Substitution Principle (LSP)

Definition: subclasses should be replaceable for their base classes without affecting program correctness.

Python example:

# 违反LSP的例子
class Bird:
    def fly(self):
        pass

class Duck(Bird):
    def fly(self):
        print("Duck flying")

class Ostrich(Bird):
    # 鸵鸟不会飞
    def fly(self):
        raise Exception("Can't fly")

# 遵循LSP的重构
class Bird:
    pass

class FlyingBird(Bird):
    def fly(self):
        pass

class Duck(FlyingBird):
    def fly(self):
        print("Duck flying")

class Ostrich(Bird):
    pass

Benefits: enhances code robustness and ensures logical inheritance relationships.

5. Interface Segregation Principle (ISP)

Definition: clients should not be forced to depend on interfaces they do not use.

Python example:

# 违反ISP的例子
class Machine:
    def print(self, document):
        pass
    def fax(self, document):
        pass
    def scan(self, document):
        pass

class MultiFunctionPrinter(Machine):
    def print(self, document):
        print("Printing")
    def fax(self, document):
        print("Faxing")
    def scan(self, document):
        print("Scanning")

class OldFashionedPrinter(Machine):
    def print(self, document):
        print("Printing")
    def fax(self, document):
        raise NotImplementedError
    def scan(self, document):
        raise NotImplementedError

# 遵循ISP的重构
from abc import ABC, abstractmethod

class Printer(ABC):
    @abstractmethod
    def print(self, document):
        pass

class Scanner(ABC):
    @abstractmethod
    def scan(self, document):
        pass

class Fax(ABC):
    @abstractmethod
    def fax(self, document):
        pass

class MultiFunctionDevice(Printer, Scanner, Fax):
    def print(self, document):
        print("Printing")
    def fax(self, document):
        print("Faxing")
    def scan(self, document):
        print("Scanning")

class OldFashionedPrinter(Printer):
    def print(self, document):
        print("Printing")

Benefits: reduces unnecessary dependencies, improves system flexibility and maintainability.

6. Dependency Inversion Principle (DIP)

Definition: high‑level modules should not depend on low‑level modules; both should depend on abstractions. Abstractions should not depend on details; details should depend on abstractions.

Python example:

# 违反DIP的例子
class LightBulb:
    def turn_on(self):
        print("LightBulb: turned on")
    def turn_off(self):
        print("LightBulb: turned off")

class ElectricPowerSwitch:
    def __init__(self, bulb: LightBulb):
        self.bulb = bulb
        self.on = False
    def press(self):
        if self.on:
            self.bulb.turn_off()
            self.on = False
        else:
            self.bulb.turn_on()
            self.on = True

# 遵循DIP的重构
from abc import ABC, abstractmethod

class Switchable(ABC):
    @abstractmethod
    def turn_on(self):
        pass
    @abstractmethod
    def turn_off(self):
        pass

class LightBulb(Switchable):
    def turn_on(self):
        print("LightBulb: turned on")
    def turn_off(self):
        print("LightBulb: turned off")

class Fan(Switchable):
    def turn_on(self):
        print("Fan: turned on")
    def turn_off(self):
        print("Fan: turned off")

class ElectricPowerSwitch:
    def __init__(self, device: Switchable):
        self.device = device
        self.on = False
    def press(self):
        if self.on:
            self.device.turn_off()
            self.on = False
        else:
            self.device.turn_on()
            self.on = True

Benefits: lowers coupling between modules, improves testability and maintainability.

7. Other Important Design Principles

DRY (Don’t Repeat Yourself): avoid duplicate code.

KISS (Keep It Simple, Stupid): keep solutions simple.

Composition over inheritance: prefer composition.

Law of Demeter: interact only with immediate friends.

8. Practical Application Advice

Avoid over‑design: apply principles proportionally to project size.

Pythonic approach: leverage Python’s dynamic features.

Iterative refactoring: improve design gradually.

Test‑driven development: ensure refactoring does not break existing functionality.

Conclusion

Mastering object‑oriented design principles is essential for becoming an advanced Python developer. The SOLID principles provide a solid guide for building robust, maintainable systems. Remember that principles are tools, not dogma; apply them flexibly according to the concrete context of your projects.

software architecturePythonOOPdesign principlesSOLID
php中文网 Courses
Written by

php中文网 Courses

php中文网's platform for the latest courses and technical articles, helping PHP learners advance quickly.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.