Python中的对象回滚、写时复制、版本代理等
前提:给定一个Python对象obj
,我想把它传递给某个随机函数。当这个函数完成后,我需要能够将obj
恢复到它最初的状态。此外,不能对obj
进行任何实际的修改,因为其他代码可能还需要访问它的原始状态。
理想的解决方案应该在大多数情况下快速处理,因为通常情况下一个大的obj
只会稍微被修改。而在不常见的情况下,如果需要将obj
恢复到之前的状态,性能就没那么重要了。
这些要求和简单复制对象的粗暴解决方案是不同的:在大多数情况下,这种方法会非常慢,而在不常见的回滚情况下却会非常快。
这个解决方案应该允许处理对象的代码像对待普通对象一样对待它。这包括给它赋予各种属性,甚至是自定义类。显然,解决方案需要考虑整个对象树。可能需要做一些妥协。我目前考虑过的一些限制包括要求非基本类型都继承自一个特殊的基类,禁止使用字典和列表,而用元组和自定义字典类来替代等等。某些重大妥协可能是可以接受的。
我已经在这个问题上工作了一段时间,想看看更有经验的Python高手有什么想法和建议。
编辑:Fred的回答让我意识到一个缺失的要求:不能对原始的obj
进行任何修改,因为原始状态也是很重要的。
2 个回答
0
看看这个备忘录设计模式
1
其实我现在已经实现了两个解决方案,看到没有其他答案,我就来分享一个吧。
最简单的解决方案是使用按需复制。假设我们有一个代理对象P
,它指向一个真实对象O
:P
会有一个__getattr__
方法,这样当你尝试访问P.x
时,它会从O.x
复制数据,并同时把这个数据存储到P.x
。这样一来,以后再访问P.x
时,就不会再调用__getattr__
了,而对P.x
的修改也不会影响到原来的O
。
这里面有一些实现细节:
P
中删除的属性;如果P
和O
合并,删除的属性也必须从O
中删除。
dict
、list
等)编写自定义的深度复制程序,确保在复制的dict
、list
等中,把所有的O
对象替换成代理P
。
ProxyDict
、ProxyList
等。
尽管如此,和效果的复杂性相比,这个解决方案非常容易理解:代理只需复制任何被访问的数据。