1.单例和工厂函数
区别
| 维度 | 单例 | 工厂(无缓存) |
|---|---|---|
| 内存 | 一份实例 + 一份连接池 | 每实例独立内存 + 独立连接池 |
| 连接池 | 共享,TCP 复用 | 各建各的,易打满文件描述符 |
| CPU | 初始化一次 | 每次都要构造 + 可能的 TLS 握手 |
| GC 压力 | 无 | 实例用完才回收,高峰时频繁 GC |
单例的代码
from functools import lru_cache
# 最多缓存 128 组不同参数的结果,可以存128次不同的调用
@lru_cache(maxsize=128) # 最多缓存 128 组不同参数的结果
def expensive(x, y):
print(f"real compute {x},{y}")
return x + y
工厂函数的代码
- 和普通函数一样写法
2.with用法
- 最常见的场景就是"资源管理",比如文件,锁,redis等操作
- 每次进入 with 都重新定义一次函数
| 场景 | 用 with 的效果 |
|---|---|
| 文件 | with open(...) as f: 自动关 |
| 锁 | with lock: 自动解 |
| 数据库/Redis | with RedisStore(...) as s: 自动 close |
| 临时修改全局状态 | with temp_set_env(): 自动恢复 |
| 计时/日志 | with timer: 一定记录 |
3.关于类的单例
- 只有当你把"实例"挂在模块顶层 ,并且永远只 import 这个实例、不再手动
类()新建时,它才是"事实单例"。 - 类本身不会因为你"先调用一次"就变成单例;一旦有人再写
类(),仍然会得到全新对象。