- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我需要确保 dict
只能接受某种类型的对象作为值。它还必须是可拾取的。这是我的第一次尝试:
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)
如果我用下面的代码(python 3.5)测试它
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)
我收到错误:TypeError: isinstance() arg 2 must be a type or tuple of types
。
它似乎没有为 _dict_type
加载正确的值,而是使用默认的 None
。
此外,它似乎依赖于协议(protocol),就好像它与 protocol=0
但是,如果我重写 __reduce__
方法并调用 super,一切都会神奇地起作用。
def __reduce__(self):
return super().__reduce__()
这怎么可能?这两个类 (w/o __reduce__
) 不应该是等价的吗?我错过了什么?
最佳答案
How it is possible? Shouldn't be the two classes (w/o
__reduce__
) equivalent? What am I missing?
您错过了一个关键步骤:如果没有 __reduce__
方法(或者它失败了!),它将使用其他方法来 pickle 您的类。因此,具有 __reduce__
的类的行为与没有 __reduce__
的类的行为不同(有几种特殊方法具有类似的行为)!
在您的第一种情况下,它将默认为基本的 dict
转储和加载,然后处理子类逻辑。因此它将使用多个 __setitem__
调用创建字典,然后设置实例属性。但是您的__setitem__
需要实例属性 _dict_type
。如果没有,它将默认为 class 属性 None
,这将失败并返回
TypeError: isinstance() arg 2 must be a type or tuple of types
这就是为什么如果你想在没有 __reduce__
的情况下 pickle 你的 TypedDict
如果它不包含任何键值对,它就会起作用。因为它不会调用 __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__
失败的普通字典不同 - 它确实适用于子类(但如果您不尝试不要实现 __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})
关于python - 在没有 __reduce__ 方法的情况下 pickle 字典子类不会加载成员属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46526498/
我知道为了可picklable,类必须覆盖__reduce__方法,并且它必须返回字符串或元组。 这个功能是如何工作的?__reduce__ 的具体用法是什么?什么时候会用到? 最佳答案 当您尝试pi
import pickle import os class Inject(object): def __reduce__(self): return (os.system
我不明白 __reduce__ 函数在 Python 中的 pickle 模块中是如何工作的。 假设我有以下类(class): class Foo(object): def __init__(se
我知道这些方法是用于 pickle/解酸的,与 reduce 内置函数无关,但 2 有什么区别,为什么我们都需要? 最佳答案 The docs这么说 If provided, at pickling
我需要确保 dict 只能接受某种类型的对象作为值。它还必须是可拾取的。这是我的第一次尝试: import pickle class TypedDict(dict): _dict_type =
我想为属于我的扩展库的对象实现 pickle 支持。有一个在启动时初始化的类服务的全局实例。所有这些对象都是作为某些服务方法调用的结果而产生的,并且本质上属于它。服务知道如何将它们序列化为二进制缓冲区
我正在努力制作一些 cython 对象,并且对使用 __setstate_ 有疑问对比 __reduce__ .好像当你pickle.loads()带有 __setstate__ 的对象方法和__ci
我是一名优秀的程序员,十分优秀!