我使用Inspyred库编写了一个用于设计优化的代码及其遗传算法的实现。从本质上讲,优化过程会在单个数据结构上创建大量变体,在我的情况下这是一个嵌套字典。
为了减少进程中使用的内存量,我一直在尝试创建某种差异字典类型,它只存储与基本字典不同的项目。其原因在于,在典型情况下,数据结构中95%的数据不会在任何变体中被修改,但数据结构的任何部分都可以包含变体。因此,出于灵活性原因,我希望数据类型的行为或多或少像字典,但只存储更改。
这是我尝试创建此内容的结果:
#!/usr/bin/python
import unittest
import copy
global_base={}
class DifferentialDict(object):
"""
dictionary with differential storage of changes
all DifferentialDict objects have the same base dictionary
"""
def __init__(self,base=None):
global global_base
self.changes={}
if not base==None:
self.set_base(base)
def set_base(self,base):
global global_base
global_base=copy.deepcopy(base)
def __copy__(self):
return self
def __deepcopy__(self):
new=DifferentialDict()
new.changes=copy.deepcopy(self.changes)
return new
def get(self):
global global_base
outdict=copy.deepcopy(global_base)
for key in self.changes:
outdict[key]=self.changes[key]
return outdict
def __setitem__(self,key,value):
self.changes[key]=value
def __getitem__(self,key):
global global_base
if key in self.changes:
return self.changes[key]
else:
return global_base[key]
class TestDifferentialDict(unittest.TestCase):
def test1(self):
ldict={'a':{1:2,3:4},'b':{'c':[1,2,3],'d':'abc'}}
ddict=DifferentialDict(base=ldict)
self.assertEqual(ddict['a'],{1:2,3:4})
ddict['a']=5
self.assertEqual(ddict['a'],5)
def test2(self):
ldict={'a':{1:2,3:4},'b':{'c':[1,2,3],'d':'abc'}}
ddict1=DifferentialDict(base=ldict)
ddict2=DifferentialDict(base=ldict)
ddict1['a'][3]=5
ddict2['a'][3]=7
self.assertEqual(ddict1['a'][3],5)
self.assertEqual(ddict2['a'][3],7)
def test3(self):
ldict={'a':{1:2,3:4},'b':{'c':[1,2,3],'d':'abc'}}
ddict1=DifferentialDict(base=ldict)
ddict2=ddict1.__deepcopy__()
ddict1['a'][3]=5
ddict2['a'][3]=7
self.assertEqual(ddict1['a'][3],5)
self.assertEqual(ddict2['a'][3],7)
if __name__ == "__main__":
unittest.main()
它适用于简单的字典,但是当新字典嵌套在主字典中时会出现故障。我知道这是因为这些二级字典是真正的Python字典而不是我的DifferentialDict的实例化,导致覆盖global_base中的条目而不是self.changes中的更改。但是,它们必须是因为所有DifferentialDict实例共享相同的基本字典。我可以添加一个'入门级'每个DifferentialDict实例化的关键,但我的感觉是有一个更优雅的解决方案,使我望而却步。
我真的很感激有关如何在嵌套时使我的差异字典工作的任何建议。提前谢谢!
答案 0 :(得分:3)
我现在没有时间尝试这个(可能稍后),但这里有两个观察结果:
如果你使用元组作为索引,例如像dict[(5,3,2)]
这样你就不会有这个问题。如果你的基础词典或差异词语基于此,你可以避免这个问题。
也许您甚至可以编写一些将dict[a][b][c]
重写为dict[(a,b,c)]
的类,以使此内部更改透明。
我不明白你为什么要使用全球基地。从我的角度来看,这使得代码更加复杂而不添加任何东西。为什么不直接存储基数:
def MyDict(collections.abc.MutableSequence):
def __init__(self, base):
self._base = base
my_global_base = dict()
d = MyDict(my_global_base)
d[2] = 'abc' # modifies self._base inside of the instance too, because it is the
# same object
如果您想更改基本内容的所有内容,只需使用popitem()
删除所有项目,然后使用update()
添加新项目。这样,由于全局变量,您的代码更灵活,并且没有任何令人惊讶的行为。
当重新实现序列,词典等类时,使用Python提供的abstract base classes可能会派上用场,它们会为您完成一些实现工作。