Python 中的对象回滚、写时复制、版本化代理等
前提:给定一个Python对象obj
,我想将它传递给一些随机函数,并且当该函数完成时,我需要重置的选项obj
恢复到其原始状态。此外,无法对 obj 进行任何实际更改,因为其他代码可能仍希望访问其原始状态。
在仅稍微修改大型 obj
的常见情况下,最佳解决方案应该很快。对于需要回滚 obj 的罕见情况,性能不太重要。
这些要求与简单复制对象的强力解决方案是正交的:在常见情况下它会慢得离谱,而对于不常见的回滚来说会非常快。
该解决方案通常应该允许处理该对象的代码将其视为普通对象。这包括为其分配各种属性,包括自定义类。显然,该解决方案需要考虑整个对象树。可能需要一些让步。到目前为止,我在解决方案中考虑的限制示例包括要求非基本类型全部从特殊基类继承、不允许用字典和列表来交换元组和自定义字典类等。大奥秘可能是可以接受的。
我已经为此工作了一段时间,很想看看更有经验的 Python 向导可能有什么想法和建议。
Edit: Fred's answer made me realize a missing requirement: No changes can be made to the original
obj
, as the original state is also valuable.Premise: Given a Python object obj
, I want to pass it along to some random function, and, when the function is done, I need the option to reset obj
to it's original state. Additionally, no actual changes can be made to the obj
as other code may still want to access it's original state.
The optimal solution should be quick in the common case where a large obj
is only slightly modified. Performance for the uncommon case where an obj
needs to be rolled back is less important.
Those requirements are orthogonal to the brute force solution of simply copying the object: It would be ridiculously slow in the common case, and super fast for the uncommon roll-back.
The solution should generally allow the code working on the object to treat it as a normal object. This includes assigning all sorts of attributes to it, including custom classes. Obviously, the solution needs to take into consideration the entire object tree. Some concessions may be needed. Examples of restrictions I've considered in my solutions so far include requiring non-basic types to all inherit from a special base class, disallowing dicts and lists in exchange for tuples and a custom dict class etc. Major arcana may be acceptable.
I've been working on this for a while, and would love to see if what ideas and suggestions more experienced Python wizards may have.
Edit: Fred's answer made me realize a missing requirement: No changes can be made to the original
obj
, as the original state is also valuable.如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
到目前为止,我实际上已经对这个问题实现了两种解决方案,鉴于没有其他答案,我不妨分享一个。
最简单的解决方案是使用按需复制。如果我们有一个代理
P
目标对象O
:P
将有一个__getattr__
方法,这样当尝试 Px
时,它尝试从Ox
复制,同时将其存储在Px
上。这会导致将来对Px
的访问永远不会到达__getattr__
,并且对Px
的修改不会影响原始内容。有很多实现细节:
P
中删除的属性列表;如果P
与O
合并,则删除的属性必须从O
中删除。dict
、list
等)编写自定义深度复制例程 - 确保将所有对象O
替换为代理<复制的dict
、list
等中的code>P即便如此,与效果的复杂性相比,这是一个非常容易理解的解决方案:代理只需复制所访问的任何数据。
I've actually implemented two solutions to this question by now, and seeing as there are no other answers, I might as well share one.
The easiest solution is to use Copy On Demand. If we have a proxy
P
targeting objectO
:P
will have a__getattr__
method so that whenP.x
is attempted, it tries to copy fromO.x
, storing it onP.x
at the same time. This has the effect that future access ofP.x
will never reach__getattr__
, and modifications toP.x
will not affect the original.There are a bunch of implementation details:
P
; ifP
is merged withO
, the deleted attributes must be deleted fromO
.dict
,list
, etc - making sure to replace all objectsO
with a proxyP
in the copieddict
,list
, etc.ProxyDict
,ProxyList
etc if desired.Even so, compared to the complexity of the effect, it is a very easy to understand solution: The proxy simply copies any data that is accessed.
了解 Memento 设计模式
这是一个 python 示例
Take a look into Memento design pattern
Here's a example for python