python - 不能用递归引用腌制对象
问题描述
我想创建一组这些对象并腌制/解开它们。但是,如果存在递归引用,例如:
mdp1 = MDP(0, (0,1))
mdp2 = MDP(0, (0,2))
mdp1.adj = frozenset({mdp2})
mdp2.adj = frozenset({mdp1})
mdps = {mdp1, mdp2}
p_on = open("test.pickle", "wb")
pickle.dump(mdps, p_on)
p_on.close()
p_off = open("test.pickle", "rb")
emp = pickle.load(p_off)
print(emp)
在这种情况下mdp1.adj
containsmdp2
和mdp2
contains mdp1
。
作为一个最小的可重现示例:
import pickle
class MDP(object):
def __init__(self, level, state_var):
self.state_var = state_var
self.level = level
self.adj = frozenset()
self.mer = frozenset()
...
def __repr__(self):
return "level {} var {} mer {}".format(self.level, self.state_var, self.mer)
def __eq__(self, other):
if isinstance(other, MDP):
return (self.level == other.level and self.state_var == other.state_var and self.mer==other.mer)
else:
return False
def __hash__(self):
return hash(self.__repr__())
def __lt__(self, other):
return self.state_var < other.state_var
def main():
mdp1 = MDP(0, (0,1))
mdp2 = MDP(0, (0,2))
mdp1.adj = frozenset({mdp2})
mdp2.adj = frozenset({mdp1})
mdps = {mdp1, mdp2}
p_on = open("test.pickle", "wb")
pickle.dump(mdps, p_on)
p_on.close()
p_off = open("test.pickle", "rb")
emp = pickle.load(p_off)
print(emp)
main()
我得到以下堆栈跟踪:
Traceback (most recent call last):
File "../test.py", line 43, in <module>
main()
File "../test.py", line 39, in main
emp = pickle.load(p_off)
File "../test.py", line 22, in __hash__
return hash(self.__repr__())
File "../test.py", line 13, in __repr__
return "level {} var {} mer {}".format(self.level, self.state_var, self.mer)
AttributeError: 'MDP' object has no attribute 'level'
解决方案
对于任何有相同问题的人,user2357112帮助解释了在 unpickling 过程中:由于循环引用,在 unpickling 过程中,一些对象将不得不看到其他对象处于未初始化或部分初始化状态,并且 pickle 不知道什么情况那是安全的还是不安全的。它最终尝试在设置级别之前将 MDP 实例添加到调整集。
这是因为我在课堂上定义散列函数和相等性的方式。删除这些自定义定义并让 python 处理相等和散列解决了我的问题。Pickle 能够使用循环引用序列化对象:https ://pymotw.com/2/pickle/#circular-references
推荐阅读
- c# - 如何在“if”条件语句中检查对象属性的存在
- python - 嵌套列表到嵌套字典
- aws-lambda - 如何修复有关 AWS Lambda 上的 Import dlib 的错误?
- javascript - 有没有办法在导航列表项上添加“悬停下拉菜单”?
- java - 如何发出仅更新提供的字段的 POST 请求?
- python - Kivy TextInput input_type 在 iOS 上不起作用
- sql - 根据列值将一行拆分为多行
- python - 矢量化距离计算的有效方法
- json - 如何避免 JSON 文件中的冗余?
- spring-data-jpa - 处理时间长的带有 JPA 锁的 Spring