使用 __setitem__ 在嵌套字典中设置项目 [英] Setting an Item in nested dictionary with __setitem__

查看:26
本文介绍了使用 __setitem__ 在嵌套字典中设置项目的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

 类数据库(对象):def __init__(self, name):self.name = 姓名self.db = anydbm.open(name, 'c')def __getitem__(self, key):键 = str(键)尝试:self.db = anydbm.open(self.name, 'w')除了例外,e:提高e别的:返回 cPickle.loads(self.db[key])最后:self.db.close()def __setitem__(self, key, value):键 = str(键)值 = cPickle.dumps(value)尝试:self.db = anydbm.open(self.name, 'w')除了例外,e:打印e别的:self.db[key] = 值最后:self.db.close()

当我尝试在嵌套的 dict 中定义新键时,似乎 getitem 返回的是一个值而不是引用,因此在 setitem 之后最终没有修改定义.

<预><代码>>>>从数据库导入数据库>>>db = 数据库('测试')>>>db['a'] = {'alpha':'aaa'}>>>db['a']['alpha'] = 'bbb'>>>打印数据库{'a': {'alpha': 'aaa'}}//值没有被修改

解决方案

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

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

相当于

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

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

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

你首先从磁盘加载字典

tmp = db.__getitem__('a') # 除了 tmp 被压入堆栈

然后改变这个字典:

tmp['alpha'] = 'bbb'

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

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

顺便说一句,您正在编写 shelve.它有同样的问题:

<块引用>

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

Here's what I did, trying to create a wrapper for a dict-like database, 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 dict nested within, it seems getitem is returning a value instead of a reference, so the definition is not finally modified after the 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

解决方案

Well, you have to understand what you are doing:

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

is equivalent to

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

so this dumps the dict to the 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 obviously has no effect on the data dumped to disk, because your object is not involved anymore.

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're writing shelve. It has the same problem:

Because of Python semantics, a shelf cannot know when a mutable persistent-dictionary entry is modified. By default modified objects are written only when assigned to the shelf (see Example). If the optional writeback parameter is set to True, all entries accessed are also cached in memory, and written back on sync() and close(); this can make it handier to mutate mutable entries in the persistent dictionary, but, if many entries are accessed, it can consume vast amounts of memory for the cache, and it can make the close operation very slow since all accessed entries are written back (there is no way to determine which accessed entries are mutable, nor which ones were actually mutated).

这篇关于使用 __setitem__ 在嵌套字典中设置项目的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆