我正在设计一个面向对象的数据结构,从用户的角度来看应该很简单,例如通过方法链接(又名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)
在临时范围,我在寻找一种方式的链条被终止后,回到老版本的number
。在绝望的边缘,我能想到的丑陋解决方案,如“实例复制”的:
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
然而,实际工作中类和对象与我的工作包含大量的数据,属性,方法,甚至子类。所以我们应该避免在每一种方法中拷贝实例,除了它涉及丑陋的代码。
有没有办法解决这个问题,通过(静静地)在链的第一个元素上创建一个副本一次?或者通过摧毁链条末端所做的任何更改? (需要注意的是现实世界的“变化”涉及许多不同,可交换不仅仅是增加数量等方法)
接受的解决方案应该执行必要的操作内部,即不打扰用户界面:
# These are NOT accepted solutions:
number.copy().add(4).add(12)
number.add(4).add(12).undo()
如果除了自我复制之外没有其他直接的解决方案,问题将会是:这样做的最优雅的方式是维持代码可读性并保持内存使用率低的最优方法是什么?例如,通过自我复制功能来装饰每种类别的方法?
我不明白该对象如何自动检测“临时范围”的结束 - 除非可能通过编写自己的基于python的语言,甚至是...... FWIW,所有“流畅的接口“到目前为止,我所看到的实现方式都是对对象进行变异或返回副本。 –