我需要确保import pickle
class TypedDict(dict):
_dict_type = None
def __init__(self, dict_type, *args, **kwargs):
super().__init__(*args, **kwargs)
self._dict_type = dict_type
def __setitem__(self, key, value):
if not isinstance(value, self._dict_type):
raise TypeError('Wrong type')
super().__setitem__(key, value)
只能接受某种类型的对象作为值。它也必须是可挑选的。
这是我的第一次尝试:
my_dict = TypedDict(int)
my_dict['foo'] = 98
with open('out.pkl', 'wb') as fin:
pickle.dump(my_dict, fin)
with open('out.pkl', 'rb') as fin:
out = pickle.load(fin)
如果我使用以下代码(python 3.5)测试它
TypeError: isinstance() arg 2 must be a type or tuple of types
我收到错误:_dict_type
。
它似乎没有为None
加载正确的值,而是使用默认的protocol=0
。
此外,它似乎依赖于协议,好像它与__reduce__
但是,如果我覆盖def __reduce__(self):
return super().__reduce__()
方法,只需调用超级内容就可以神奇地工作。
__reduce__
怎么可能?不应该是两个类(w {o package util1;
public class Utility {
public static void method() {
System.out.println("First Utility. static method");
}
}
)等价?我错过了什么?
答案 0 :(得分:3)
怎么可能?不应该是两个类(w {o
__reduce__
)等价?我错过了什么?
你错过了一个至关重要的步骤:如果没有__reduce__
方法(或者它失败了!)它将使用其他方法来挑选你的课程。因此,__reduce__
的班级不会像没有__reduce__
的班级一样(有几种特殊的方法就像那样)!
在第一种情况下,它将默认为基本dict
转储和加载,然后处理子类逻辑。因此,它将使用多个__setitem__
调用创建字典,然后设置实例属性。但是,您的__setitem__
需要实例属性 _dict_type
。如果它没有,它将默认为类属性 None
,但
TypeError: isinstance() arg 2 must be a type or tuple of types
如果您希望在没有TypedDict
的情况下挑选__reduce__
,如果它不包含任何键值对,那么它的原因是什么。因为它不会调用__setitem__
,然后设置实例属性:
my_dict = TypedDict(int)
with open('out.pkl', 'wb') as fin:
pickle.dump(my_dict, fin)
with open('out.pkl', 'rb') as fin:
out = pickle.load(fin)
print(out._dict_type) # int
另一方面,如果您实施__reduce__
方法,它可以正常工作,因为与__reduce__
失败的普通词典不同 - 它确实适用于子类(但如果您不这样做,则不会尝试#&# 39; t实现__reduce__
):
>>> d = {1: 1}
>>> dict.__reduce__(d)
TypeError: "can't pickle dict objects"
>>> d = TypedDict(int)
>>> dict.__reduce__(d)
(<function copyreg._reconstructor>,
(__main__.TypedDict, dict, {}),
{'_dict_type': int})