Python:测试字典(dict)条目是否已修改
我为Python:测试字典(dict)条目是否已修改,python,dictionary,wrapper,Python,Dictionary,Wrapper,我为dict内置类编写了一个小包装器,该类在第一次访问相应的键时从cPickled文件加载字典的条目(值)。当字典被销毁时,所有加载的条目都会写回磁盘 现在,如果我可以检查是否有任何值已更改,并只写出那些实际上已更改的值,那将是很方便的因此,我的问题是:字典是否知道某个值是否已更改?还是有一种聪明的方法可以透明地实现这一点? 为了完整起见,我附上了我使用的代码。它通过存储文件的路径(键用作文件名)和存在文件的键列表来调用 import cPickle class DictDB(dict):
dict
内置类编写了一个小包装器,该类在第一次访问相应的键时从cPickle
d文件加载字典的条目(值)。当字典被销毁时,所有加载的条目都会写回磁盘
现在,如果我可以检查是否有任何值已更改,并只写出那些实际上已更改的值,那将是很方便的因此,我的问题是:字典是否知道某个值是否已更改?还是有一种聪明的方法可以透明地实现这一点?
为了完整起见,我附上了我使用的代码。它通过存储文件的路径(键用作文件名)和存在文件的键列表来调用
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()
我认为您可以覆盖
\uuuu setitem\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuo()方法,以跟踪值的更改,将更改后的值存储在列表中,并使用此。然后简单地将它们与进行比较=
选择要写出的值。如果内存允许,您可以保留从磁盘读取的原始值的副本,并在close()
方法中比较当前值与原始值,只写出更改
此方法在可以放入字典的内容方面提供了更多的自由,因为元素不需要跟踪对它们所做的更改。我可以使用一种发布-订阅模型,其中包含的字典订阅每个子字典(或其他值)。然后,当其中一个被编辑时,它会通知包含它的任何词典
如果您不希望它们都处理这方面的连接,并且愿意允许包含字典只检查访问时的更改或以设定的间隔检查更改,那么可以让每个包含的对象跟踪版本
编号。然后,当包含字典准备就绪时,它只需检查版本号是否已更改
最后一种可能性是有一种可靠地计算所包含对象的哈希值的方法。这将允许您编写一个外部函数,并消除对象跟踪其自身版本的需要,但也有其自身的复杂性,因为您需要对所有对象重载\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
函数,可以识别对象并从中获取某种智能哈希值是的,它们几乎总是dict
本身。看到Janne的评论,我注意到我应该提到的是,值本身不会被替换,而是会被修改,这意味着DictDB.\uu setitem()__
将不会被调用(我猜)但最终你是对的,我需要更进一步,使用dict类的另一个包装器作为值。问题确实是,当一个对象(如列表
或dict
作为值存储在父dict
中)被更改时,不会调用\uuu setitem()。这当然是可能的,但由于这些值是大对象,我不想保留它们的两个副本。(事实上,它们太大了,我只能根据请求单独加载它们,否则我只能pickle
整个dict
)和Janne的想法相同,我的评论也一样:)我最终得到了你的第一个建议;最后,这意味着我还必须包装存储在父词典中的所有list
和dict
对象,以便它们在发生更改时通知父词典。