Python 使用property 重构类
重构的实例
重构前的设计问题
Phone类中同时存在get_device_id()方法和device_id属性,造成了接口的不一致性- 初始化逻辑分散,设备 ID 的获取可能在多个地方发生
PackageManager需要了解Phone类的内部实现细节
1 | class Phone: |
重构后
1 | class Phone: |
改进点:
a) 使用懒加载模式:
- 只在真正需要 device_id 时才去获取
- 避免了重复的检查和获取逻辑
b) 简化接口:
- 移除了
get_device_id()方法,统一使用 property - 将设备检测逻辑移到私有方法中,隐藏内部实现细节
c) 更清晰的职责划分:
Phone类完全负责设备 ID 的管理和获取PackageManager只需要关心设备是否可用
好的重构通常遵循以下原则:
- 保持行为不变 - 外部接口和功能保持一致
- 提高可读性 - 代码更容易理解
- 提高可维护性 - 更容易修改和扩展
- 减少重复 - 消除重复代码
- 单一职责 - 每个类和方法只做一件事
重构小技巧
Python 在重构时有许多独特且强大的优势:
动态特性优势
- 鸭子类型(Duck Typing):允许更灵活的代码重构
- 动态属性和方法:可以轻松替换和修改类的行为
反射和自省能力
1
2
3
4# 动态检查和修改对象属性
hasattr(obj, 'method') # 检查方法是否存在
getattr(obj, 'method', default_value) # 安全获取属性
setattr(obj, 'new_method', new_function) # 动态添加方法装饰器
在不修改原函数的情况下添加功能
1
2
3
4
5
6
7
8
9def logger(func):
def wrapper(*args, **kwargs):
print(f"Calling {func.__name__}")
return func(*args, **kwargs)
return wrapper
def some_function():
pass # 无需修改原函数即可添加日志上下文管理器
简化资源管理和异常处理
1
2
3
4
5
6
7
8class RefactoredResource:
def __enter__(self):
# 资源初始化
return self
def __exit__(self, exc_type, exc_val, exc_tb):
# 资源清理
pass类型提示(Type Hints)
提供代码重构时的静态类型检查
1
2
3
4
5
6
7from typing import List, Optional, Union
def refactored_function(
items: List[str],
optional_param: Optional[int] = None
) -> Union[str, None]:
pass函数式编程特性
1
2
3# 使用 lambda 和高阶函数重构
numbers = [1, 2, 3, 4]
squared = list(map(lambda x: x**2, numbers))Property 装饰器
1
2
3
4
5
6
7
8
9
10
11
12
13class RefactoredClass:
def __init__(self):
self._value = None
def value(self):
# 可以添加计算逻辑
return self._value
def value(self, new_value):
# 可以添加验证逻辑
self._value = new_value元编程
1
2
3
4
5
6
7
8
9def add_method(cls):
def new_method(self):
print("Dynamically added method")
setattr(cls, 'dynamic_method', new_method)
return cls
class MyClass:
pass数据类和 Dataclasses
1
2
3
4
5
6from dataclasses import dataclass, field
class RefactoredData:
name: str
value: int = field(default=0)魔法方法(Magic Methods)
1
2
3
4
5
6
7
8class SmartCompare:
def __eq__(self, other):
# 自定义相等比较
pass
def __lt__(self, other):
# 自定义小于比较
pass
示例:
1 | # 重构前 |