Skip to main content
 首页 » 编程设计

python之Python 中的对象回滚、写时复制、版本化代理等

2025年05月04日10del

前提:给定一个 Python 对象 obj,我想将它传递给某个随机函数,并且当函数完成时,我需要重置选项obj 到它的原始状态。此外,不能对 obj 进行任何实际更改,因为其他代码可能仍想访问它的原始状态。


在仅对大型 obj 进行轻微修改的常见情况下,最佳解决方案应该很快。对于需要回滚 obj 的罕见情况,性能不太重要。

这些要求与简单复制对象的蛮力解决方案是正交的:在常见情况下它会慢得离谱,但在不常见的回滚情况下会非常快。

解决方案通常应允许处理对象的代码将其视为普通对象。这包括为其分配各种属性,包括自定义类。显然,解决方案需要考虑到整个对象树。可能需要一些让步。到目前为止,我在我的解决方案中考虑的限制示例包括要求非基本类型全部继承自特殊基类,不允许用字典和列表来交换元组和自定义字典类等。大奥秘可能是可以接受的。

我已经研究了一段时间,很想看看更有经验的 Python 向导是否有什么想法和建议。


编辑:Fred 的回答让我意识到一个遗漏的要求:不能对原始 obj 进行任何更改,因为原始状态也很有值(value)。

请您参考如下方法:

到目前为止,我实际上已经针对这个问题实现了两种解决方案,鉴于没有其他答案,我不妨分享一个。

最简单的解决方案是使用按需复制。如果我们有一个代理 P 目标对象 O:P 将有一个 __getattr__ 方法,这样当 P.x 尝试,它尝试从O.x 复制,同时将其存储在P.x 上。这具有以下效果:以后对 P.x 的访问将永远不会到达 __getattr__,并且对 P.x 的修改不会影响原始内容。

有一堆实现细节:

  • 维护从 P 中删除的属性列表;如果 P 与 O 合并,删除的属性必须从 O 中删除。
  • 为任何支持的数据类型编写自定义深度复制例程,例如 dict、list 等 - 确保替换所有对象 O 在复制的 dict、list 等中使用代理 P。
  • 如果需要,编写 ProxyDict、ProxyList 等。
  • 确保代理链(即代理到代理的代理)正常工作。这基本上意味着当代理到代理需要查看属性是否存在时避免副作用。
  • 实现将代理向下合并到被代理对象的方法,并将其完全拆分,从被代理对象复制剩余数据。

    即便如此,与效果的复杂性相比,这是一个非常容易理解的解决方案:代理简单地复制任何访问的数据。