在方法链接期间临时保留对对象的更改

Keep changes to an object temporary during method chaining

我正在设计一个面向对象的数据结构,从用户的角度来看应该易于处理,例如,通过方法链接(又名 Fluent interface)。但是,每个更改都应该暂时 作用于对象:在该链内,但不能超出该链。
这是一个按预期工作的简化示例:

class C:
    def __init__(self, num):
        self.sum = num

    def add(self, num=0):
        self.sum += num
        return self

number = C(23)
number.add(7).add(12).sum
# 42
number.sum
# 42 (but I expect: 23)

在这种情况下,.add() 永久 更改为 number。但是,只有这样才能进行永久更改:

# This is the only way how a user should make permanent changes:
number = number.add(4).add(12)

temporary 范围内,我正在寻找一种在链终止后返回到旧版本 number 的方法。在绝望的边缘,我可以想到像 "instance replication":

这样丑陋的解决方案
class C2:
    def __init__(self, num):
        self.sum = num

    def add(self, num=0):
        self2 = C2(self.sum) # or equivalently: self2 = copy.deepcopy(self)
        self2.sum += num
        return self2

number = C2(23)
number.add(7).add(12).sum
# 42
number.sum
# 23

然而,我正在处理的实际 classes 和对象包含大量数据、属性、方法,甚至 subclasses。所以我们应该避免在每个方法中复制实例,除了它涉及丑陋的代码之外。

有没有办法解决这个问题,例如通过(默默地)在链的第一个元素上只创建一个副本?或者通过销毁链末端所做的任何更改? (请注意,现实世界 "changes" 涉及许多不同的、可交换的方法,而不仅仅是添加数字)

公认的解决方案应该在内部执行必要的操作,即不影响用户界面:

# These are NOT accepted solutions:
number.copy().add(4).add(12)
number.add(4).add(12).undo()

如果除了自我复制之外没有直接的解决方案,问题将是:保持代码可读性和保持低内存使用率的最优雅的方法是什么?例如,通过自我复制功能装饰每个 class 方法?

不是修改调用方法的对象,而是return修改后的副本:

class C:
    def __init__(self, num):
        self.sum = num

    def add(self, num=0):
        return C(self.sum + num)

number = C(23)
assert number.add(7).add(12).sum == 42
assert number.sum == 23

有关此解决方案中内存处理的详细信息,请参阅此帖子的评论。此解决方案是解决您问题的标准方法。