【问题标题】:Setting an Item in nested dictionary with __setitem__使用 __setitem__ 在嵌套字典中设置项目
【发布时间】:2026-01-10 18:10:02
【问题描述】:

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

    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

【问题讨论】:

  • 我不知道问题的标题是否正确。随意编辑您认为最好的内容。

标签: python wrapper


【解决方案1】:

好吧,你必须明白你在做什么:

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

等价于

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

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

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

你首先从磁盘加载字典

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

然后改变这个字典:

tmp['alpha'] = 'bbb'

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

要完成这项工作,您不能返回简单的 dict,而是需要另一个对象来跟踪更改并将它们写回磁盘。

顺便说一句,你写的是shelve。它有同样的问题:

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

【讨论】: