2

我将让以下终端会话说明一切:

>>> import shelve
>>> s = shelve.open('TestShelve')
>>> from collections import deque
>>> s['store'] = deque()
>>> d = s['store']
>>> print s['store']
deque([])
>>> print d
deque([])
>>> s['store'].appendleft('Teststr')
>>> d.appendleft('Teststr')
>>> print s['store']
deque([])
>>> print d
deque(['Teststr'])

不应该ds['store']指向同一个对象吗?为什么可以appendleft工作d但不能工作s['store']

4

2 回答 2

3

shelve正在pickle处理(序列化)对象。当然,这会产生一个副本。因此,您返回的对象shelve不会与您放入的对象具有相同的身份,尽管它们是等价的。

如果它很重要,您可以编写一个deque在修改时自动重新上架的子类,尽管这在许多用例中可能性能很差。

于 2012-06-21T20:15:08.903 回答
2

事实证明它们并不相同,因此您对它们执行的任何操作都不匹配:

>>> import shelve
>>> s = shelve.open('TestShelve')
>>> from collections import deque
>>> s['store'] = deque()
>>> d = s['store']
>>> id(s['store'])
27439296
>>> id(d)
27439184

要在编码时修改项目,您需要传递参数writeback=True

s = shelve.open('TestShelve', writeback=True)

请参阅文档:

如果 writeback 参数为 True,则对象将保存所有访问条目的缓存,并在同步和关闭时间将它们写回 dict。这允许对可变条目进行自然操作,但会消耗更多内存并使同步和关闭需要很长时间。

您也可以这样做,writeback=False但您需要完全按照提供的示例编写代码:

# having opened d without writeback=True, you need to code carefully:
temp = d['xx']      # extracts the copy
temp.append(5)      # mutates the copy
d['xx'] = temp      # stores the copy right back, to persist it
于 2012-06-21T20:14:12.830 回答