Ho scritto un codice per l'ottimizzazione del progetto utilizzando la libreria Inspyred e la sua implementazione di Algoritmi genetici. In sostanza, il processo di ottimizzazione crea un gran numero di variazioni su una singola struttura di dati, che è un dizionario annidato nel mio caso.Dizionario Python che memorizza solo le modifiche
Per ridurre la quantità di memoria utilizzata nel processo, ho cercato di creare una sorta di tipo di dizionario differenziale, che memorizza solo elementi diversi dal dizionario di base. La ragione di ciò è che in un caso tipico, il 95% dei dati nella struttura dati non verrà modificato in nessuna delle varianti, ma qualsiasi parte della struttura dati può contenere variazioni. Quindi, per motivi di flessibilità, mi piacerebbe avere un tipo di dati che si comporta più o meno come un dizionario, ma memorizza solo le modifiche.
questo è il risultato del mio tentativo di creare questa:
#!/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()
Funziona bene per un dizionario semplice, ma si rompe quando i nuovi dizionari sono annidati all'interno del dizionario principale. Capisco che ciò avvenga perché questi dizionari di secondo livello sono veri dizionari Python invece di istanze del mio DifferentialDict, risultanti in una sovrascrittura di voci in global_base piuttosto che in modifiche in self.changes. Tuttavia, devono essere a causa della premessa che tutte le istanze di DifferentialDict condividono lo stesso dizionario di base. Potrei aggiungere una chiave "entry level" a ogni istanza di DifferentialDict, ma la mia sensazione è che ci sia una soluzione più elegante che mi sfugge.
Apprezzerei molto qualsiasi suggerimento su come far funzionare il mio dizionario differenziale quando nidificato. Grazie in anticipo!
Quali test stanno passando e quali falliscono? – RafaelC
I test 2 e 3 falliscono, 1 passaggi. –
Ho appena trovato questa libreria: [dictdiffer] (https: // github.com/inveniosoftware/dictdiffer) che potrebbe già implementarlo. Su Hacker News c'è una discussione a riguardo dove raymondh mostra come farlo con dizionari non nidificati [in puro Python] (https://news.ycombinator.com/item?id=5771696). –