【发布时间】:2018-05-21 02:49:44
【问题描述】:
这看起来很简单,但我找不到好的解决方案。
这是旧的“按引用传递”/“按值传递”/“按对象引用传递”问题。我了解正在发生的事情,但我找不到一个好的工作。
我知道小问题的解决方案,但我的状态非常大并且保存/重新计算非常昂贵。鉴于这些限制,我找不到解决方案。
这里有一些简单的伪代码来说明我想做的事情(如果 Python 允许我通过引用传递的话):
class A:
def __init__(self,x):
self.g=x
self.changes=[]
def change_something(self,what,new): # I want to pass 'what' by reference
old=what # and then de-reference it here to read the value
self.changes.append([what,old]) # store a reference
what=new # dereference and change the value
def undo_changes():
for c in self.changes:
c[0]=c[1] # dereference and restore old value
编辑:添加更多伪代码以显示我希望如何使用上述内容
test=A(1) # initialise test.g as 1
print(test.g)
out: 1
test.change_something(test.g,2)
# if my imaginary code above functioned as described in its comments,
# this would change test.g to 2 and store the old value in the list of changes
print(test.g)
out: 2
test.undo_changes()
print(test.g)
out: 1
显然,由于“通过对象引用”,上述代码在 python 中不起作用。此外,我希望能够撤消单个更改,而不仅仅是上面代码中的所有更改。
问题是……我似乎找不到好的工作。有这样的解决方案:
Do/Undo using command pattern in Python
这涉及存储一堆命令。然后,“撤消”涉及删除最后一个命令,然后通过获取初始状态并重新应用除最后一个命令之外的所有内容来重建最终状态。我的状态太大了,这不可行,问题是:
- 状态非常大。完全保存它非常昂贵。
- “执行”操作代价高昂(无法从保存的状态重新计算)。
- Do 操作也是不确定的,依赖于随机输入。
- 撤消操作非常频繁
我有一个想法,即确保所有内容都存储在列表中,并编写我的代码以便存储、读取和写入这些列表中的所有内容。然后在上面的代码中,每次我想读/写一个变量时,我都可以传递列表名称和列表索引。
基本上这相当于在 Python 中构建我自己的内存架构和 C 风格的指针系统! 这行得通,但似乎有点……荒谬?肯定有更好的方法吗?
【问题讨论】:
-
我认为您可以复制您的内容并存储其副本。
-
问题是如何存储“什么”的位置,以便以后从副本中恢复旧值?
-
另外,如果我没记错的话,当你将参数传递给 Python 中的函数时,你传递的是对对象的引用。然后,当您重新分配变量时,旧对象不会更改。
-
你能提供你的
what是什么数据类型吗? -
我认为这就是您想要的 github.com/ActiveState/code/blob/master/recipes/Python/… - 使用它的两个配套配方,它将记录一系列更改并提供撤消/重做。我唯一想添加的是某种“快照”以及恢复到任何快照的能力。