gpt4 book ai didi

python - 在没有 __reduce__ 方法的情况下 pickle 字典子类不会加载成员属性

转载 作者:太空狗 更新时间:2023-10-30 01:19:25 24 4
gpt4 key购买 nike

我需要确保 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/

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