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

发布于 2024-10-14 07:39:59 字数 674 浏览 9 评论 0原文

前提:给定一个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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

笑饮青盏花 2024-10-21 07:40:00

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

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

有很多实现细节:

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

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

  • 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 object O: P will have a __getattr__ method so that when P.x is attempted, it tries to copy from O.x, storing it on P.x at the same time. This has the effect that future access of P.x will never reach __getattr__, and modifications to P.x will not affect the original.

    There are a bunch of implementation details:

  • Maintaining a list of attributes that are deleted from P; if P is merged with O, the deleted attributes must be deleted from O.
  • Writing custom deep copying routines for any supported datatypes, such as dict, list, etc - making sure to replace all objects O with a proxy P in the copied dict, list, etc.
  • Writing ProxyDict, ProxyList etc if desired.
  • Making sure proxy chains, that is proxy to a proxy, works. This basically means to avoid side effects when a proxy to a proxy needs to see if an attribute exists.
  • Implementing methods for merging the proxy downwards into the proxied object, and splitting it entirely, copying in remaining data from the proxied object.

    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.

  • 情愿 2024-10-21 07:40:00

    Take a look into Memento design pattern

    Here's a example for python

    ~没有更多了~
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文