1. 面向对象编程三大特性解析
面向对象编程(OOP)是现代编程语言的基石,Python作为一门多范式语言,其面向对象特性尤为强大。在实际项目中,合理运用封装、继承和多态这三大特性,能够显著提升代码的可维护性和扩展性。让我们深入探讨这些特性的实现细节和最佳实践。
1.1 封装:数据隐藏的艺术
封装的核心在于"信息隐藏",通过访问控制机制保护对象的内部状态。Python采用命名约定而非强制限制来实现封装,这种设计哲学体现了"我们都是成年人"的理念。
私有属性的实现机制值得深入研究。当使用双下划线前缀(如__name)时,Python解释器会进行名称改写(name mangling),将属性名转换为_类名__属性名的形式。这种改写发生在编译阶段,是一种轻量级的访问控制。
python复制class SecureData:
def __init__(self):
self.__secret = "TopSecret123" # 会被改写为_SecureData__secret
self._internal = "ForInternalUse" # 约定俗成的保护属性
def get_secret(self):
return self.__secret[-3:] # 安全地暴露部分信息
实际开发中,单下划线前缀的属性(_var)通常表示"保护"成员,虽然语法上可访问,但约定不应在类外部直接使用。这种约定在团队协作和大型项目中尤为重要。
私有属性的典型应用场景包括:
- 敏感数据保护(如密码、密钥)
- 防止子类意外重写关键属性
- 实现内部状态管理机制
1.2 继承:代码复用的利器
Python的继承系统支持单继承和多继承,新式类(继承自object)的方法解析顺序(MRO)采用C3线性化算法,这保证了菱形继承情况下的方法调用确定性。
python复制class Animal:
def __init__(self, name):
self.name = name
def speak(self):
raise NotImplementedError("子类必须实现此方法")
class Mammal(Animal):
def __init__(self, name, gestation_period):
super().__init__(name)
self.gestation = gestation_period
def feed_young(self):
print(f"{self.name}正在哺乳幼崽")
class Platypus(Mammal, Animal): # 实际不需要重复声明Animal
def speak(self):
print("嘎嘎嘎") # 鸭嘴兽的特殊叫声
方法重写的三种方式各有适用场景:
父类名.方法名(self):明确指定父类调用,适用于多重继承super().方法名():推荐方式,自动遵循MRO顺序super(子类名,self).方法名():显式指定起始点,用于复杂继承结构
在Python 3中,所有类都是新式类,即使不显式继承object。建议始终使用新式类写法,即
class MyClass(object):,以保持代码一致性。
1.3 多态:接口统一的魅力
Python的多态是"鸭子类型"的体现:只要对象实现了相应方法,就可以被视为特定类型。这种动态特性使得代码更加灵活。
python复制class PaymentGateway:
def process_payment(self, amount):
"""支付网关基类"""
raise NotImplementedError
class Alipay(PaymentGateway):
def process_payment(self, amount):
print(f"支付宝支付:{amount}元")
class WechatPay(PaymentGateway):
def process_payment(self, amount):
print(f"微信支付:{amount}元")
def checkout(payment_method, amount):
"""统一支付接口"""
payment_method.process_payment(amount)
# 使用示例
payment = Alipay() if user_choice == "alipay" else WechatPay()
checkout(payment, 100.50)
多态的优势在大型系统中尤为明显:
- 新增支付方式无需修改checkout函数
- 便于单元测试(可传入Mock对象)
- 支持运行时动态切换实现
2. 方法类型深度解析
Python中的三类方法各有其设计目的和使用场景,正确选择方法类型可以使代码更加清晰和高效。
2.1 实例方法:对象行为的载体
实例方法是面向对象编程中最常用的方法类型,其第一个参数self指向调用该方法的实例。在内存使用上,实例方法比静态方法和类方法占用更多资源,因为每个方法绑定到一个具体实例。
python复制class UserProfile:
def __init__(self, username):
self.username = username
self.login_count = 0
def increment_login(self):
"""实例方法典型用例"""
self.login_count += 1
self._update_last_login()
def _update_last_login(self):
"""保护方法:仅供内部使用"""
self.last_login = datetime.now()
实例方法的最佳实践:
- 方法逻辑需要访问或修改实例状态时使用
- 保护方法使用单下划线前缀(_method)
- 避免在实例方法中直接操作类属性(应使用类方法)
2.2 类方法:类级别操作的利器
类方法通过@classmethod装饰器定义,第一个参数cls指向类本身。类方法最常见的用途是作为工厂方法,提供替代构造函数的创建对象方式。
python复制class DatabaseConnection:
_pool = {} # 类属性维护连接池
def __init__(self, connection_string):
self.conn = self._create_connection(connection_string)
@classmethod
def from_config(cls, config_name):
"""工厂方法:根据配置名创建连接"""
config = load_db_config(config_name)
if config_name not in cls._pool:
cls._pool[config_name] = cls(config['connection_string'])
return cls._pool[config_name]
@classmethod
def get_pool_size(cls):
"""类级别状态查询"""
return len(cls._pool)
类方法的高级应用场景:
- 实现单例模式或对象池模式
- 提供多种构造对象的途径
- 维护和查询类级别状态
2.3 静态方法:工具函数的归宿
静态方法通过@staticmethod装饰器定义,不与类或实例绑定,实质上是放在类命名空间中的普通函数。静态方法常用于工具函数或辅助方法。
python复制class DataValidator:
@staticmethod
def validate_email(email):
"""邮箱格式验证"""
pattern = r'^[\w\.-]+@[\w\.-]+\.\w+$'
return re.match(pattern, email) is not None
@staticmethod
def validate_phone(phone, country_code='CN'):
"""电话号码验证"""
# 根据不同国家代码应用不同验证规则
validators = {
'CN': lambda p: len(p) == 11 and p.isdigit(),
'US': lambda p: re.match(r'^\d{3}-\d{3}-\d{4}$', p)
}
return validators.get(country_code, lambda _: False)(phone)
静态方法的使用建议:
- 将逻辑上相关但不依赖实例/类状态的函数组织在一起
- 替代模块级别的工具函数,提高代码组织性
- 避免在静态方法中通过硬编码类名访问类属性
3. 高级特性与实战技巧
3.1 属性访问控制进阶
Python提供了@property装饰器实现更精细的属性访问控制,这是封装的高级形式。
python复制class Temperature:
def __init__(self, celsius):
self._celsius = celsius
@property
def celsius(self):
"""获取摄氏温度"""
return self._celsius
@celsius.setter
def celsius(self, value):
"""设置摄氏温度,进行合法性检查"""
if value < -273.15:
raise ValueError("温度不能低于绝对零度")
self._celsius = value
@property
def fahrenheit(self):
"""计算华氏温度(只读属性)"""
return self._celsius * 9/5 + 32
属性装饰器的优势:
- 保持简单属性访问语法
- 添加访问控制逻辑而不破坏现有代码
- 实现计算属性和延迟加载
3.2 多重继承的MRO机制
Python使用C3线性化算法确定方法解析顺序(MRO),理解这一机制对设计复杂继承关系至关重要。
python复制class A:
def method(self):
print("A.method")
class B(A):
def method(self):
print("B.method")
super().method()
class C(A):
def method(self):
print("C.method")
super().method()
class D(B, C):
def method(self):
print("D.method")
super().method()
d = D()
d.method()
# 输出顺序:D -> B -> C -> A
print(D.__mro__) # 显示方法解析顺序
MRO的实际应用技巧:
- 使用super()而非硬编码父类名调用方法
- 通过
类名.__mro__查看方法解析顺序 - 避免设计过于复杂的多重继承结构
3.3 抽象基类与接口定义
Python的abc模块支持抽象基类定义,这是实现多态的更规范方式。
python复制from abc import ABC, abstractmethod
class GraphicShape(ABC):
@abstractmethod
def draw(self):
pass
@abstractmethod
def area(self):
pass
class Circle(GraphicShape):
def __init__(self, radius):
self.radius = radius
def draw(self):
print(f"绘制圆形,半径:{self.radius}")
def area(self):
return 3.14 * self.radius ** 2
# 使用示例
shape = Circle(5) # 必须实现所有抽象方法
shape.draw()
print("面积:", shape.area())
抽象基类的最佳实践:
- 定义清晰的接口契约
- 确保子类实现所有抽象方法
- 结合register方法实现接口注册机制
4. 设计模式实战应用
4.1 工厂模式实现
结合类方法和继承实现灵活的工厂模式。
python复制class LoggerFactory:
@classmethod
def get_logger(cls, logger_type):
"""日志工厂方法"""
loggers = {
'file': FileLogger,
'console': ConsoleLogger,
'database': DatabaseLogger
}
logger_class = loggers.get(logger_type, ConsoleLogger)
return logger_class()
class FileLogger:
def log(self, message):
with open('app.log', 'a') as f:
f.write(f"{datetime.now()}: {message}\n")
class ConsoleLogger:
def log(self, message):
print(f"[LOG] {message}")
# 使用示例
logger = LoggerFactory.get_logger('file')
logger.log("系统启动完成")
工厂模式的优势:
- 集中管理对象创建逻辑
- 客户端代码与具体实现解耦
- 便于扩展新的产品类型
4.2 策略模式实现
利用多态实现策略模式,使算法可相互替换。
python复制class SortStrategy:
"""排序策略接口"""
def sort(self, data):
raise NotImplementedError
class QuickSort(SortStrategy):
def sort(self, data):
print("执行快速排序")
# 实际实现省略...
return sorted(data)
class MergeSort(SortStrategy):
def sort(self, data):
print("执行归并排序")
# 实际实现省略...
return sorted(data)
class Sorter:
def __init__(self, strategy=None):
self._strategy = strategy or QuickSort()
def set_strategy(self, strategy):
self._strategy = strategy
def perform_sort(self, data):
return self._strategy.sort(data)
# 使用示例
data = [5, 2, 8, 1, 9]
sorter = Sorter()
sorter.perform_sort(data)
sorter.set_strategy(MergeSort())
sorter.perform_sort(data)
策略模式的应用场景:
- 一个任务有多种实现方式
- 需要在运行时切换算法
- 隔离算法实现和使用代码
4.3 观察者模式实现
利用Python的动态特性实现轻量级观察者模式。
python复制class NewsPublisher:
def __init__(self):
self._subscribers = []
def subscribe(self, subscriber):
if subscriber not in self._subscribers:
self._subscribers.append(subscriber)
def unsubscribe(self, subscriber):
if subscriber in self._subscribers:
self._subscribers.remove(subscriber)
def notify(self, news):
for subscriber in self._subscribers:
subscriber.update(news)
class EmailSubscriber:
def update(self, news):
print(f"邮件发送:最新消息 - {news}")
class SMSSubscriber:
def update(self, news):
print(f"短信通知:{news}")
# 使用示例
publisher = NewsPublisher()
publisher.subscribe(EmailSubscriber())
publisher.subscribe(SMSSubscriber())
publisher.notify("Python 3.12正式发布!")
观察者模式的实现要点:
- 定义清晰的订阅/通知接口
- 处理好循环引用问题
- 考虑使用weakref避免内存泄漏
5. 性能优化与高级技巧
5.1 使用__slots__优化内存
对于需要创建大量实例的类,__slots__可以显著减少内存占用。
python复制class Point:
__slots__ = ('x', 'y') # 固定属性列表
def __init__(self, x, y):
self.x = x
self.y = y
# 对比测试
class RegularPoint:
def __init__(self, x, y):
self.x = x
self.y = y
# 内存占用测试
import sys
p1 = Point(1, 2)
p2 = RegularPoint(1, 2)
print(sys.getsizeof(p1)) # 通常更小
print(sys.getsizeof(p2)) # 通常更大
__slots__的使用注意事项:
- 子类需要重新定义
__slots__ - 不能动态添加新属性
- 适合属性固定的场景
5.2 描述符协议高级应用
描述符协议(__get__, __set__, __delete__)可以实现更强大的属性控制。
python复制class ValidatedAttribute:
"""验证型描述符"""
def __init__(self, name, validator):
self.name = name
self.validator = validator
def __get__(self, instance, owner):
if instance is None:
return self
return instance.__dict__[self.name]
def __set__(self, instance, value):
if not self.validator(value):
raise ValueError(f"无效的{self.name}")
instance.__dict__[self.name] = value
class Person:
age = ValidatedAttribute('age', lambda x: 0 <= x <= 150)
name = ValidatedAttribute('name', lambda x: isinstance(x, str) and len(x) < 50)
def __init__(self, name, age):
self.name = name
self.age = age
# 使用示例
p = Person("Alice", 30)
try:
p.age = 200 # 触发验证错误
except ValueError as e:
print(e)
描述符的高级应用:
- 实现类型检查系统
- 创建延迟加载属性
- 构建ORM映射系统
5.3 元类编程实战
元类(metaclass)允许在类创建时进行干预,实现高级模式。
python复制class SingletonMeta(type):
"""单例模式元类"""
_instances = {}
def __call__(cls, *args, **kwargs):
if cls not in cls._instances:
cls._instances[cls] = super().__call__(*args, **kwargs)
return cls._instances[cls]
class DatabaseConnection(metaclass=SingletonMeta):
def __init__(self):
print("创建数据库连接")
# 实际连接代码...
# 使用示例
conn1 = DatabaseConnection()
conn2 = DatabaseConnection()
print(conn1 is conn2) # 输出True,是同一个实例
元类编程的应用场景:
- 实现设计模式(如单例、工厂)
- 自动注册子类
- API框架中的类验证
- ORM中的表映射
6. 常见问题与解决方案
6.1 继承中的初始化问题
多重继承时,__init__方法的调用需要特别注意。
python复制class A:
def __init__(self):
print("A.__init__")
super().__init__()
class B:
def __init__(self):
print("B.__init__")
super().__init__()
class C(A, B):
def __init__(self):
print("C.__init__")
super().__init__()
# 测试
c = C()
# 输出顺序:C -> A -> B
解决方案:
- 始终使用super()调用父类方法
- 确保所有父类也使用super()
- 在多重继承中明确方法解析顺序
6.2 混入类(Mixin)模式
混入类是一种特殊的多重继承用法,用于添加功能而非表示"是什么"关系。
python复制class JSONSerializableMixin:
def to_json(self):
import json
return json.dumps(self.__dict__)
class XMLSerializableMixin:
def to_xml(self):
from xml.etree.ElementTree import Element, tostring
elem = Element(self.__class__.__name__)
for key, value in self.__dict__.items():
child = Element(key)
child.text = str(value)
elem.append(child)
return tostring(elem)
class Person(JSONSerializableMixin, XMLSerializableMixin):
def __init__(self, name, age):
self.name = name
self.age = age
# 使用示例
p = Person("Bob", 25)
print(p.to_json())
print(p.to_xml())
混入类的最佳实践:
- 命名以Mixin后缀
- 不定义自己的实例属性
- 只添加特定功能
6.3 动态属性访问
Python的__getattr__和__getattribute__允许动态属性处理。
python复制class DynamicAttributes:
def __init__(self):
self._data = {}
def __getattr__(self, name):
"""仅在常规属性查找失败时调用"""
if name in self._data:
return self._data[name]
raise AttributeError(f"'DynamicAttributes'对象没有属性'{name}'")
def __setattr__(self, name, value):
"""设置属性时调用"""
if name == '_data':
super().__setattr__(name, value)
else:
self._data[name] = value
# 使用示例
obj = DynamicAttributes()
obj.test = 42
print(obj.test) # 输出42
print(obj.nonexistent) # 触发AttributeError
动态属性访问的应用:
- 实现代理模式
- 动态API包装器
- 属性访问日志
7. 测试与调试技巧
7.1 单元测试策略
针对面向对象代码的测试方法需要特别考虑继承和多态。
python复制import unittest
class TestPaymentGateway(unittest.TestCase):
def test_alipay(self):
gateway = Alipay()
# 测试支付处理
with self.assertLogs(level='INFO') as cm:
gateway.process_payment(100)
self.assertIn("支付宝支付", cm.output[0])
def test_wechat_pay(self):
gateway = WechatPay()
# 测试支付处理
with self.assertLogs(level='INFO') as cm:
gateway.process_payment(200)
self.assertIn("微信支付", cm.output[0])
class TestPolymorphism(unittest.TestCase):
def test_payment_polymorphism(self):
"""测试多态行为"""
gateways = [Alipay(), WechatPay()]
for gateway in gateways:
with self.subTest(gateway=type(gateway).__name__):
with self.assertLogs(level='INFO'):
gateway.process_payment(50)
测试面向对象代码的建议:
- 为每个重要类创建测试用例
- 测试继承链上的所有方法重写
- 验证多态行为
- 使用Mock对象隔离测试
7.2 调试技巧
面向对象代码的调试需要特殊工具和技术。
python复制# 使用pdb调试器检查对象状态
import pdb
class ComplexObject:
def __init__(self):
self.data = {"key": "value"}
self.counter = 0
def process(self):
pdb.set_trace() # 设置断点
for i in range(5):
self.counter += i
print(f"Processing {i}")
# 调试会话示例
obj = ComplexObject()
obj.process()
调试技巧:
- 使用
dir(obj)查看对象属性和方法 vars(obj)查看实例字典type(obj)获取对象类型isinstance(obj, cls)检查类型hasattr(obj, 'attr')检查属性存在性
7.3 性能分析
面向对象代码的性能分析需要关注方法调用开销。
python复制import cProfile
from pstats import Stats
class PerformanceTest:
def method1(self):
return sum(i*i for i in range(10000))
def method2(self):
total = 0
for i in range(10000):
total += i*i
return total
# 性能分析
pr = cProfile.Profile()
pr.enable()
test = PerformanceTest()
for _ in range(1000):
test.method1()
test.method2()
pr.disable()
stats = Stats(pr)
stats.sort_stats('time').print_stats(10)
性能优化建议:
- 减少不必要的属性访问
- 考虑使用
__slots__ - 避免在循环中创建临时对象
- 对热点方法使用静态方法或函数
8. 项目结构设计建议
8.1 模块化组织
合理的模块划分可以提高面向对象代码的可维护性。
code复制my_project/
├── core/ # 核心业务逻辑
│ ├── __init__.py
│ ├── models.py # 数据模型类
│ ├── services.py # 服务类
│ └── exceptions.py # 自定义异常
├── utils/ # 工具类
│ ├── __init__.py
│ ├── validators.py # 验证工具
│ └── serializers.py # 序列化工具
├── tests/ # 测试代码
│ ├── __init__.py
│ ├── test_models.py
│ └── test_services.py
└── main.py # 程序入口
模块化设计原则:
- 每个模块/包职责单一
- 避免循环导入
- 合理使用
__init__.py暴露接口 - 遵循PEP 8命名规范
8.2 接口设计规范
良好的接口设计是面向对象编程的关键。
python复制from abc import ABC, abstractmethod
from typing import List, Dict
class DataStorage(ABC):
"""数据存储接口"""
@abstractmethod
def save(self, data: Dict) -> bool:
"""保存数据"""
pass
@abstractmethod
def load(self, identifier: str) -> Dict:
"""加载数据"""
pass
@abstractmethod
def query(self, conditions: Dict) -> List[Dict]:
"""查询数据"""
pass
class DatabaseStorage(DataStorage):
"""数据库存储实现"""
def save(self, data: Dict) -> bool:
# 具体实现
return True
# 必须实现所有抽象方法
接口设计建议:
- 使用抽象基类明确接口
- 添加类型注解提高可读性
- 保持接口简洁专注
- 文档字符串说明契约
8.3 文档与注释
良好的文档对面向对象代码至关重要。
python复制class Customer:
"""代表系统中的客户实体
属性:
name (str): 客户全名
email (str): 联系邮箱
loyalty_points (int): 累计忠诚度积分
"""
def __init__(self, name: str, email: str):
"""初始化新客户
参数:
name: 客户名称
email: 验证过的邮箱地址
异常:
ValueError: 如果邮箱格式无效
"""
self.name = name
self.email = email
self.loyalty_points = 0
def add_points(self, points: int) -> None:
"""增加忠诚度积分
参数:
points: 要增加的正整数积分
异常:
ValueError: 如果points为负数
"""
if points < 0:
raise ValueError("积分不能为负")
self.loyalty_points += points
文档规范:
- 类文档说明职责和重要属性
- 方法文档说明参数、返回值和异常
- 使用类型注解
- 保持文档与代码同步
9. 现代Python特性应用
9.1 数据类简化代码
Python 3.7+的数据类(dataclass)可以大幅简化纯数据类的定义。
python复制from dataclasses import dataclass, field
from typing import List
@dataclass
class InventoryItem:
"""库存商品项"""
name: str
unit_price: float
quantity: int = 0
tags: List[str] = field(default_factory=list)
def total_cost(self) -> float:
return self.unit_price * self.quantity
# 使用示例
item = InventoryItem("Widget", 9.99, 5)
print(item) # 自动生成__repr__
数据类的优势:
- 自动生成
__init__,__repr__等方法 - 类型提示集成
- 通过
field()自定义字段行为 - 减少样板代码
9.2 类型提示进阶
Python的类型提示系统可以用于面向对象设计的契约检查。
python复制from typing import Generic, TypeVar, Optional
T = TypeVar('T')
class Stack(Generic[T]):
"""泛型栈实现"""
def __init__(self) -> None:
self._items: List[T] = []
def push(self, item: T) -> None:
self._items.append(item)
def pop(self) -> T:
return self._items.pop()
def peek(self) -> Optional[T]:
return self._items[-1] if self._items else None
类型提示的最佳实践:
- 对公共API进行全面注解
- 使用泛型处理容器类
- 结合mypy进行静态检查
- 区分必需和可选参数
9.3 上下文管理器协议
通过__enter__和__exit__实现资源管理。
python复制class DatabaseConnection:
def __init__(self, connection_string):
self.conn = None
self.connection_string = connection_string
def __enter__(self):
self.conn = connect_to_db(self.connection_string)
return self.conn
def __exit__(self, exc_type, exc_val, exc_tb):
if self.conn:
self.conn.close()
if exc_type:
print(f"连接异常: {exc_val}")
return False # 不抑制异常
# 使用示例
with DatabaseConnection("db://user:pass@host/db") as conn:
conn.execute("SELECT * FROM users")
上下文管理器的应用:
- 资源获取/释放
- 事务管理
- 临时状态设置
- 超时控制
10. 架构设计思考
10.1 组合优于继承
现代面向对象设计更倾向于组合而非深层次的继承。
python复制class Engine:
def start(self):
print("引擎启动")
class Wheels:
def rotate(self):
print("车轮转动")
class Car:
def __init__(self):
self.engine = Engine()
self.wheels = [Wheels() for _ in range(4)]
def drive(self):
self.engine.start()
for wheel in self.wheels:
wheel.rotate()
# 使用示例
car = Car()
car.drive()
组合的优势:
- 更灵活的运行时行为修改
- 避免复杂的继承层次
- 更清晰的职责划分
- 便于单元测试
10.2 依赖注入实践
依赖注入可以提高代码的可测试性和灵活性。
python复制class UserService:
def __init__(self, storage):
"""接受存储依赖注入"""
self.storage = storage
def register_user(self, user_data):
if self.storage.user_exists(user_data['username']):
raise ValueError("用户已存在")
return self.storage.create_user(user_data)
# 使用示例
db_storage = DatabaseStorage()
user_service = UserService(db_storage)
# 测试时可以使用Mock
mock_storage = MockStorage()
test_service = UserService(mock_storage)
依赖注入的原则:
- 通过构造函数注入主要依赖
- 保持注入接口简单
- 考虑使用依赖注入框架(如injector)
- 避免服务定位器模式
10.3 领域驱动设计
领域驱动设计(DDD)在复杂系统中特别有效。
python复制class Order:
"""订单聚合根"""
def __init__(self, order_id, customer):
self.id = order_id
self.customer = customer
self._items = []
self._status = "created"
def add_item(self, product, quantity):
"""添加订单项"""
if self._status != "created":
raise ValueError("订单已确认,不能修改")
self._items.append(OrderItem(product, quantity))
def confirm(self):
"""确认订单"""
if not self._items:
raise ValueError("订单没有商品")
self._status = "confirmed"
self._events.append(OrderConfirmed(self.id))
class OrderItem:
"""订单项值对象"""
def __init__(self, product, quantity):
self.product = product
self.quantity = quantity
@property
def total(self):
return self.product.price * self.quantity
DDD的关键要素:
- 识别聚合根
- 区分实体和值对象
- 定义领域服务
- 使用仓储模式持久化
- 领域事件通知
11. 代码质量保障
11.1 SOLID原则应用
SOLID原则是面向对象设计的基石。
- 单一职责原则(SRP):
python复制# 违反SRP
class User:
def __init__(self, name):
self.name = name
def save(self):
# 保存到数据库...
def send_email(self, message):
# 发送邮件...
# 遵循SRP
class User:
def __init__(self, name):
self.name = name
class UserRepository:
def save(self, user):
# 保存到数据库...
class EmailService:
def send(self, user, message):
# 发送邮件...
- 开闭原则(OCP):
python复制class Shape(ABC):
@abstractmethod
def area(self):
pass
class Rectangle(Shape):
def area(self):
# 计算矩形面积...
class Circle(Shape):
def area(self):
# 计算圆形面积...
# 新增形状类型不需要修改现有代码
class Triangle(Shape):
def area(self):
# 计算三角形面积...
SOLID原则实践:
- 小类、短方法
- 依赖抽象而非实现
- 通过扩展而非修改增加功能
- 接口隔离
- 依赖倒置
11.2 设计模式识别
在现有代码中发现并应用设计模式。
python复制# 发现策略模式应用机会
def process_data(data, algorithm):
"""数据处理函数"""
return algorithm(data)
# 重构为显式策略模式
class DataProcessingStrategy(ABC):
@abstractmethod
def process(self, data):
pass
class QuickProcess(DataProcessingStrategy):
def process(self, data):
# 快速处理实现...
class PreciseProcess(DataProcessingStrategy):
def process(self, data):
# 精确处理实现...
class DataProcessor:
def __init__(self, strategy=None):
self.strategy = strategy or QuickProcess()
def process(self, data):
return self.strategy.process(data)
模式识别技巧:
- 查找if/else链考虑策略模式
- 查找全局变量考虑单例模式
- 查找回调函数考虑观察者模式
- 查找复杂对象创建考虑工厂模式
11.3 代码审查要点
面向对象代码审查的关键关注点。
python复制# 待审查代码
class UserManager:
def __init__(self):
self.users = []
def add_user(self, name, email):
# 验证逻辑与存储逻辑耦合
if '@' not in email:
raise ValueError("无效邮箱")
self.users.append({"name": name, "email": email})
def get_user(self, name):
for user in self.users:
if user['name'] == name:
return user
return None
# 审查建议:
# 1. 违反单一职责原则(验证、存储、查询在一个类中)
# 2. 使用原始字典而非User类
# 3. 查询效率低(线性搜索)
# 4. 缺乏类型提示
# 5. 没有接口抽象
审查清单:
- 类职责是否单一
- 继承层次是否合理
- 是否适当使用设计模式
- 是否有充分的测试覆盖
- 文档是否完整
- 性能是否考虑
12. 性能优化深入
12.1 方法调用优化
Python方法调用的性能特征及优化方法。
python复制import timeit
class Adder:
def add(self, a, b):
return a + b
@staticmethod
def static_add(a, b):
return a + b
def global_add(a, b):
return a + b
# 性能测试
print("实例方法:", timeit.timeit('obj.add(1, 2)',
setup='obj = Adder()', globals=globals()))
print("静态方法:", timeit.timeit('Adder.static_add(1, 2)',
globals=globals()))
print("模块函数:", timeit.timeit('global_add(1, 2)',
globals=globals()))
优化建议:
- 热点路径考虑使用静态方法或模块函数
- 避免在循环中创建临时对象
- 对性能关键代码考虑使用__slots__
- 必要时使用内置函数或C扩展
12.2 属性访问优化
属性访问的性能考虑。
python复制class Point:
def __init__(self, x, y):
self.x = x
self.y = y
class OptimizedPoint:
__slots__ = ('x', 'y')
def __init__(self, x, y):
self.x = x
self.y = y
# 测试属性访问速度
p = Point(1, 2)
op = OptimizedPoint(1, 2)
%timeit p.x # 常规属性访问
%timeit op.x # __slots__属性访问
优化技巧:
- 使用局部变量缓存频繁访问的属性
- 考虑__slots__减少内存占用
- 避免动态属性创建
- 对只读属性使用@property缓存
12.3 内存管理
面向对象代码的内存管理策略。
python复制import weakref
class DataCache:
_instances = weakref.WeakValueDictionary()
def __new__(cls, data_id):
"""实现缓存模式"""
if data_id in cls._instances