用生成器实现深度合并,通过yield路径三元组解耦遍历与策略,由消费者按需执行合并;支持循环引用检测、惰性求值及chainmap只读视图。

直接用迭代协议实现深度合并,不是去“遍历”字典再手动拼接,而是把合并过程本身设计成一个可迭代的、按需推进的状态机。核心在于:把嵌套结构的遍历路径和合并决策解耦,用生成器逐层 yield 合并动作,再由统一的消费者执行——这样既保持惰性,又便于调试和插入自定义逻辑。
用生成器表达合并路径
深度合并的本质是同步遍历两个嵌套结构的键空间。你可以写一个生成器函数,它不返回最终字典,而是 yield 三元组:(key_path, value_a, value_b),其中 key_path 是元组形式的路径(如 ('user', 'profile', 'tags')),value_a/b 是对应路径在两个源结构中的值。
这个生成器内部用栈或队列管理待处理的嵌套层级,每次 pop 出一对子结构,检查键交集与差集,对共有的键递归 push 下一层,对独有的键直接 yield。它天然支持跳过空值、过滤特定键、提前终止等控制流。
让合并策略成为可插拔的迭代消费者
有了路径生成器,真正的合并逻辑可以完全分离。写一个通用的 consume_merger(generator, strategy_func) 函数:
- strategy_func 接收 (path, val_a, val_b) 并返回合并后的值或 None(表示跳过)
- consumer 维护一个结果字典,按 path 逐层 setdefault 创建嵌套结构,填入返回值
- 例如:遇到列表时,strategy_func 可选择连接、去重、取并集;遇到日期对象,可选保留旧值或覆盖为新值
处理循环引用与中间状态
迭代协议天然适合带状态的合并。在生成器内部维护一个 WeakSet 记录已访问的对象 ID,遇到重复引用时 yield 特殊标记(如 ('__cycle__', id(obj))),让消费者决定是跳过、报错还是替换成占位符。这比一次性深拷贝更节省内存,也避免了递归调用栈溢出风险。
配合 ChainMap 实现只读式深度视图
如果不需要物化最终字典,而是想提供一个“合并后看起来像一个字典”的只读接口,可以把路径生成器和 ChainMap 结合:自定义一个类,其 __getitem__ 方法内部调用生成器,找到第一个匹配 path 的非 None 值并返回;__iter__ 则 yield 所有唯一 key_path 的顶层键。这样就得到了一个真正惰性、无内存拷贝、支持优先级覆盖的深度合并视图。











