使用__setitem__在嵌套字典中设置项

时间:2013-05-21 17:38:46

标签: python wrapper

这就是我所做的,尝试为类似dict的数据库创建一个包装器,以及其他函数:

    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()

当我尝试在嵌套的dict中定义一个新键时,似乎getitem返回的是一个值而不是一个引用,因此在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

1 个答案:

答案 0 :(得分:2)

嗯,你必须明白你在做什么:

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

相当于

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

所以这会将dict转储到磁盘上。但是当你这样做时

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

首先从磁盘加载dict

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

然后改变这个词:

tmp['alpha'] = 'bbb'

这显然对转储到磁盘的数据没有影响,因为您的对象不再涉及。

要使这项工作无法返回一个简单的dict,而是需要另一个跟踪更改的对象并将它们写回磁盘。

是的,你正在写shelve。它有同样的问题:

  

由于Python语义,架子无法知道何时可变   持久字典条目被修改。默认情况下修改对象   只有在分配到货架时才会写入(参见示例)。如果   可选的writeback参数设置为True,访问的所有条目都是   也缓存在内存中,并写回sync()和close();这个   可以使持久化中的可变条目变得更容易   字典,但是,如果访问了很多条目,它可能会消耗很多   缓存的内存量,它可以进行关闭操作   因为所有被访问的条目都被写回来很慢(没有办法   确定哪些访问的条目是可变的,哪些是可变的   实际上是变异的。)