Python:测试字典条目是否被修改

4 投票
4 回答
3222 浏览
提问于 2025-04-16 14:24

我写了一个小工具,它是对内置的 dict 类的一个封装。这个工具可以从 cPickle 文件中加载字典的条目(值),当你第一次访问某个键时,它会自动加载对应的值。当这个字典被销毁时,所有加载的条目会被写回到磁盘上。

现在,如果我能检查一下哪些值被改变过,然后只把那些真正改变过的值写回去,那就方便多了。所以我想问:字典能知道某个值是否被改变了吗?或者有没有什么聪明的方法可以实现这个功能?

为了完整性,我附上我使用的代码。这个代码会接收一个存储文件的路径(键用作文件名)和一个包含存在文件的键的列表。

import cPickle

class DictDB(dict):

  def __init__(self, path, folders):
    self.picklepath     = path    # path to files on disk
    self.folders        = folders # available folders
    self.loaded_folders = {}

  def has_key(self, key):
    return key in self.folders

  def get(self, key):
    if not key in self.loaded_folders.keys():
      if not key in self.folders:
        raise KeyError("Folder "+key+" not available")
      # load from disk
      self.loaded_folders[key] = cPickle.load(file(self.picklepath + key + ".cpickle2"))
    return self.loaded_folders[key]

  def __getitem__(self, key):
    return self.get(key)

  def close(self):
    for folder in self.loaded_folders.keys():
      # write back
      cPickle.dump(self.loaded_folders[folder], file(picklepath + folder + '.cpickle2', 'w'), 2)

  def __del__(self):
    self.close()

4 个回答

0

你可以存储每个值的两个副本:一个是原始状态,另一个可能是修改后的状态。然后只需要用 != 来比较这两个值,看看哪个需要写出来。

1

我觉得你可以重写一下 __setitem__() 这个方法,这样就能记录下值的变化,把改变过的值存到一个列表里,然后用这个列表来选择正确的值进行输出。

1

我可能会用一种发布-订阅的模式来处理这个问题,也就是说,包含的字典会订阅每一个子字典(或者其他值)。这样,当其中一个被编辑时,它会通知所有包含它的字典。

如果你不想让所有字典都处理这些连接的事情,并且愿意让包含的字典在访问时或者在设定的时间间隔内检查变化,你可以让每个包含的对象记录一个version编号。这样,当包含的字典准备好时,它只需要检查这个版本号是否发生了变化。

最后一种可能性是,有一种可靠的方法来计算包含对象的哈希值。这样你就可以写一个外部函数,而不需要让对象自己跟踪版本,但这也有自己的复杂性,因为你要么需要在所有对象上重载__hash__,要么需要写另一个形式的hash()函数,能够识别对象并从中提取某种智能的哈希值。

撰写回答