gpt4 book ai didi

存储在 shelf 中的 Python 实例在关闭后发生变化

转载 作者:太空宇宙 更新时间:2023-11-04 10:45:31 25 4
gpt4 key购买 nike

我认为最好的解释方式是举个例子:

>>> class Person:
... def __init__(self, brother=None):
... self.brother = brother
...
>>> bob = Person()
>>> alice = Person(brother=bob)
>>> import shelve
>>> db = shelve.open('main.db', writeback=True)
>>> db['bob'] = bob
>>> db['alice'] = alice
>>> db['bob'] is db['alice'].brother
True
>>> db['bob'] == db['alice'].brother
True
>>> db.close()
>>> db = shelve.open('main.db',writeback=True)
>>> db['bob'] is db['alice'].brother
False
>>> db['bob'] == db['alice'].brother
False

两次比较的预期输出再次为 True。然而,pickle(被shelve使用)似乎分别重新实例化了bobalice.brother .我如何使用 shelve/pickle“修复”这个问题? db['alice'].brother 是否可以指向 db['bob'] 或类似的东西?请注意,我不想只比较两者,我需要两者实际上相同。

根据 Blckknght 的建议,我尝试一次 pickle 整个字典,但问题仍然存在,因为它似乎是单独 pickle 每个键。

最佳答案

我相信您看到的问题来自 shelve 模块存储其值的方式。每个值都独立于 shelf 中的其他值进行 pickle,这意味着如果将同一对象作为值插入多个键下,则不会在键之间保留身份。但是,如果单个值对同一对象有多个引用,则标识将保留在该单个值内。

这是一个例子:

a = object() # an arbitrary object
db = shelve.open("text.db")
db['a'] = a
db['another_a'] = a
db['two_a_references'] = [a, a]
db.close()

db = shelve.open("text.db") # reopen the db
print(db['a'] is db['another_a']) # prints False
print(db['two_a_references'][0] is db['two_a_references'][1]) # prints True

第一个打印尝试确认插入数据库的对象 a 的两个版本的身份,一个直接在键 'a' 下,另一个在 'another_a' 下。它不起作用,因为单独的值是单独 pickle 的,因此它们之间的标识丢失了。

第二个打印测试是否保留了存储在键'two_a_references' 下的对a 的两个引用。因为列表是一次性 pickle 的,所以身份得以保留。

因此,要解决您的问题,您有几种选择。一种方法是避免测试身份并依赖各种对象类型中的 __eq__ 方法来确定两个对象在语义上是否相等,即使它们不是同一个对象。另一种方法是将所有数据捆绑到一个对象(例如字典)中,然后使用 pickle.dump 保存并使用 pickle.load 恢复而不是使用shelve(或者您可以改编 this recipe for a persistent dictionary ,它是从 shelve 文档链接的,并且几乎可以做到这一点)。

关于存储在 shelf 中的 Python 实例在关闭后发生变化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17636226/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com