我将让以下终端会议说明一切:
>>> 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'])
d
和s['store']
不应指向同一个对象吗?为什么appendleft
适用于d
而不适用于s['store']
?
答案 0 :(得分:3)
shelve
是pickle
(序列化)对象。必要时,这是一个副本。因此,从shelve
返回的对象与您输入的对象不具有相同的标识,尽管它们是等效的。
如果它很重要,你可以编写一个deque
子类,它会在修改时自动重新架设,尽管在许多用例中这可能会有很差的性能。
答案 1 :(得分: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