Python教程41:面向对象最佳实践
“代码是写给人看的,顺便让机器执行。”
经过前面的学习,我们掌握了OOP的所有特性。今天总结Python面向对象的最佳实践,帮助你写出更优质的代码。
1. SOLID原则
S - 单一职责原则(Single Responsibility)
一个类只做一件事:
1# 不好:类职责太多
2class User:
3 def __init__(self, name):
4 self.name = name
5
6 def save_to_database(self):
7 """保存用户"""
8 pass
9
10 def send_email(self):
11 """发送邮件"""
12 pass
13
14# 好:职责分离
15class User:
16 def __init__(self, name):
17 self.name = name
18
19class UserRepository:
20 def save(self, user):
21 """保存用户"""
22 pass
23
24class EmailService:
25 def send(self, user):
26 """发送邮件"""
27 pass
O - 开闭原则(Open/Closed)
对扩展开放,对修改关闭:
1# 好:使用多态扩展功能
2class Shape:
3 def area(self):
4 pass
5
6class Circle(Shape):
7 def __init__(self, radius):
8 self.radius = radius
9
10 def area(self):
11 return 3.14 * self.radius ** 2
12
13# 添加新形状无需修改现有代码
14class Rectangle(Shape):
15 def __init__(self, width, height):
16 self.width = width
17 self.height = height
18
19 def area(self):
20 return self.width * self.height
L - 里氏替换原则(Liskov Substitution)
子类必须能替换父类:
1# 不好:违反里氏替换
2class Bird:
3 def fly(self):
4 return "Flying"
5
6class Penguin(Bird):
7 def fly(self):
8 raise Exception("企鹅不会飞") # 破坏了父类约定
9
10# 好:正确的继承
11class Bird:
12 pass
13
14class FlyingBird(Bird):
15 def fly(self):
16 return "Flying"
17
18class Penguin(Bird):
19 def swim(self):
20 return "Swimming"
I - 接口隔离原则(Interface Segregation)
不应强迫实现不需要的方法:
1# 不好:接口太大
2class Worker:
3 def work(self):
4 pass
5
6 def eat(self):
7 pass
8
9# 好:接口分离
10class Workable:
11 def work(self):
12 pass
13
14class Eatable:
15 def eat(self):
16 pass
17
18class Human(Workable, Eatable):
19 def work(self):
20 return "Working"
21
22 def eat(self):
23 return "Eating"
24
25class Robot(Workable):
26 def work(self):
27 return "Working"
D - 依赖倒置原则(Dependency Inversion)
依赖抽象而不是具体:
1# 不好:依赖具体类
2class MySQLDatabase:
3 def save(self, data):
4 pass
5
6class UserService:
7 def __init__(self):
8 self.db = MySQLDatabase() # 硬编码依赖
9
10# 好:依赖抽象
11class Database:
12 def save(self, data):
13 pass
14
15class MySQLDatabase(Database):
16 def save(self, data):
17 print("Save to MySQL")
18
19class UserService:
20 def __init__(self, database: Database):
21 self.db = database # 依赖注入
2. 命名和组织
类命名
1# 使用大驼峰(PascalCase)
2class UserAccount:
3 pass
4
5class DataProcessor:
6 pass
方法命名
1class Example:
2 # 公开方法:小写+下划线
3 def public_method(self):
4 pass
5
6 # 内部方法:单下划线开头
7 def _internal_method(self):
8 pass
9
10 # 私有方法:双下划线开头
11 def __private_method(self):
12 pass
组织原则
1class WellOrganized:
2 """
3 良好组织的类:
4 1. 类属性
5 2. __init__
6 3. 特殊方法(__str__, __repr__等)
7 4. @property
8 5. @classmethod
9 6. @staticmethod
10 7. 公开方法
11 8. 私有方法
12 """
13
14 # 1. 类属性
15 class_var = "类属性"
16
17 # 2. 初始化
18 def __init__(self, value):
19 self.value = value
20
21 # 3. 特殊方法
22 def __str__(self):
23 return f"Example({self.value})"
24
25 # 4. Property
26 @property
27 def computed_value(self):
28 return self.value * 2
29
30 # 5. 类方法
31 @classmethod
32 def from_string(cls, s):
33 return cls(int(s))
34
35 # 6. 静态方法
36 @staticmethod
37 def utils_function():
38 pass
39
40 # 7. 公开方法
41 def public_method(self):
42 pass
43
44 # 8. 私有方法
45 def _private_method(self):
46 pass
3. 设计技巧
组合优于继承
1# 不好:过度使用继承
2class Animal: pass
3class Mammal(Animal): pass
4class Dog(Mammal): pass
5
6# 好:使用组合
7class Engine:
8 def start(self):
9 pass
10
11class Car:
12 def __init__(self):
13 self.engine = Engine() # 组合
14
15 def start(self):
16 self.engine.start()
使用抽象基类定义接口
1from abc import ABC, abstractmethod
2
3class PaymentProcessor(ABC):
4 @abstractmethod
5 def process_payment(self, amount):
6 pass
7
8class CreditCardProcessor(PaymentProcessor):
9 def process_payment(self, amount):
10 return f"Processing ${amount} with credit card"
使用属性而不是getter/setter
1# 不好:Java风格
2class Person:
3 def get_age(self):
4 return self._age
5
6 def set_age(self, value):
7 self._age = value
8
9# 好:Python风格
10class Person:
11 @property
12 def age(self):
13 return self._age
14
15 @age.setter
16 def age(self, value):
17 if value < 0:
18 raise ValueError("年龄不能为负")
19 self._age = value
4. 文档和类型提示
1from typing import List, Optional
2
3class User:
4 """
5 用户类
6
7 Attributes:
8 name: 用户名
9 email: 邮箱地址
10 """
11
12 def __init__(self, name: str, email: str):
13 """
14 初始化用户
15
16 Args:
17 name: 用户名
18 email: 邮箱
19 """
20 self.name = name
21 self.email = email
22
23 def send_email(self, message: str) -> bool:
24 """
25 发送邮件
26
27 Args:
28 message: 邮件内容
29
30 Returns:
31 是否发送成功
32 """
33 # 实现...
34 return True
35
36 @classmethod
37 def from_dict(cls, data: dict) -> 'User':
38 """从字典创建用户"""
39 return cls(data['name'], data['email'])
5. 小结
Python OOP最佳实践:
- SOLID原则:单一职责、开闭、里氏替换、接口隔离、依赖倒置
- 命名规范:PascalCase类名、snake_case方法名
- 设计技巧:组合优于继承、使用ABC、用property
- 文档:类型提示、文档字符串
遵循这些实践能写出更优质、更Pythonic的OOP代码。
练习题:
- 重构一段违反SOLID原则的代码
- 为现有类添加完整的类型提示和文档
- 将继承关系改为组合
本文代码示例:
关注公众号:极客老墨
更多 AI 应用开发、工程实践和效率工具分享,欢迎扫码关注。
