【问题标题】:Alternatives to copy.deepcopy; Or is it even necessary?copy.deepcopy 的替代品;还是有必要?
【发布时间】:2021-02-14 21:20:51
【问题描述】:

要从我的国际象棋引擎撤消移动,我在很大程度上依赖于良好的缓存系统,每次移动完成/撤消时都会更新该缓存系统。它还用于“回到过去”并查看较早的位置。更新代码如下所示:

self.cache.append([copy.deepcopy(self.board), ..., copy.deepcopy(self.brokenCastles)])

self.brokenCastles 是一个集合,self.board 是一个代表棋盘的二维列表。还有一些其他的列表和变量被存储(例如每一方的合法移动),因此不必在每次使用相同的棋盘时都计算它们。到目前为止,它们没有造成任何问题(或者我没有注意到它们)。

最大的问题在于self.boardself.brokenCastles。如果我只是像所有其他变量一样附加它们,则会出现大量问题(例如国王被拿走和一些奇怪的东西),这可以通过分别制作列表/集合的深度复制来解决。仅使用内置的 pythons .copy() 或使用像 [:] 这样的切片并没有帮助。 我不太清楚为什么需要 deepcopy 并且无法在较小的环境中复制该问题。所以我的问题是是否需要 deepcopy,如果需要,有没有办法让它更快,因为它是我系统目前最大的瓶颈。

缓存读取函数如下所示:

def undo_move(self):
        self.board = self.cache[-1][0]
        ... # A lot more 
        self.brokenCastles = self.cache[-1][4]
        self.cache.pop()

如果有任何细节缺失,请告诉我。感谢您的帮助。

完整代码(一团糟)可在GitHub 获得。

【问题讨论】:

  • 如果我是你,我会研究 Memento 设计模式,并为它做一个堆栈。简单来说,Memento 是一个对象,可以在其中存储您的动作,然后您甚至可以在其中创建撤消和重做功能。
  • 也许你应该创建将board 转换为更小的函数 - 即字符串的平面列表/元组 - 并将其保存在缓存中。第二个函数将这个平面列表/元组转换回board。或者也许你应该只在没有全板的情况下保留缓存。但它需要撤消所有移动以获得旧板。
  • @furas 我现在想出了一个超级卡顿解决方案(请参阅我的回答),它实际上非常快。

标签: python copy deep-copy


【解决方案1】:

我现在使用了令人难以置信的 jank bypass 解决方案:

  1. 将列表转换为字符串
  2. 使用内置的 eval 函数检索其信息

仍然很慢,但比 deepcopy 好很多。

编辑:我通过使用自己的字符串转换来加快速度:

def to_lst(my_string):
    temp = my_string.split("|")
    return [temp[i: i+8] for i in range(0, 64, 8)]


def to_str(my_list):
    return "|".join([a for b in my_list for a in b])

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-06-05
    • 1970-01-01
    • 2011-09-09
    • 1970-01-01
    • 1970-01-01
    • 2017-03-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多