Setting an item in a nested dictionary with __setitem__

Here's what I did when trying to create a wrapper for a database like dict, among other functions:

class database(object): def __init__(self, name): self.name = name self.db = anydbm.open(name, 'c') def __getitem__(self, key): key = str(key) try: self.db = anydbm.open(self.name, 'w') except Exception,e: raise e else: return cPickle.loads(self.db[key]) finally: self.db.close() def __setitem__(self, key, value): key = str(key) value = cPickle.dumps(value) try: self.db = anydbm.open(self.name, 'w') except Exception,e: print e else: self.db[key] = value finally: self.db.close() 

When I try to define a new key in a nested format, it seems that getitem returns a value instead of a link, so the definition will not be permanently changed after setitem.

 >>> from database import database >>> db = database('test') >>> db['a'] = {'alpha':'aaa'} >>> db['a']['alpha'] = 'bbb' >>> print db {'a': {'alpha': 'aaa'}} //The value is not modified 
+4
source share
1 answer

Well, you need to understand what you are doing:

 db['a'] = {'alpha':'aaa'} 

equivalently

 db.__setitem__('a', {'alpha':'aaa'}) 

therefore it issues a dict to disk. However when you do

 db['a']['alpha'] = 'bbb' 

you first load the dict from disk

 tmp = db.__getitem__('a') # except tmp is pushed on the stack 

and then change this dict:

 tmp['alpha'] = 'bbb' 

This clearly does not affect the data flushed to disk, because your object is no longer involved.

To make this work, you cannot return a simple dict, but instead you need another object that tracks changes and writes them back to disk.

Btw, you write shelve . It has the same problem:

Due to the semantics of Python, a shelf cannot know when a mutable dictionary entry changes. By default, changed objects are recorded only when a shelf is assigned (see example). If the optional writeback parameter is set to True, all the records that are accessed are also cached in memory and written back to sync () and close (); this can make it more convenient for mutating mutable records in a constant dictionary, but if many records are available, it can cache the cache, and it can do the closing operation very slowly, since all the records that were written are written (there is no way determine which available records are mutable, and which ones are actually mutated).

+2
source

Source: https://habr.com/ru/post/1482012/


All Articles