gpt4 book ai didi

python - 无法 pickle 递归嵌套的defaultdict

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

我有一个递归嵌套的 defaultdict 类定义为

from collections import defaultdict

class NestedDict(defaultdict):
def __init__(self):
super().__init__(self.__class__)

位于 nested_dict.py 文件中。

当我尝试 pickle 它时,例如

import pickle
from nested_dict import NestedDict

d = NestedDict()
pickle.loads(pickle.dumps(d))

我得到 TypeError: __init__() takes 1 positional argument but 2 were given

这里到底发生了什么?

最佳答案

defaultdict 类实现了一个 object.__reduce__() method返回的元组的第二个元素(构造函数的参数)始终是工厂对象:

>>> d = NestedDict()
>>> d.__reduce__()
(<class '__main__.NestedDict'>, (<class '__main__.NestedDict'>,), None, None, <dict_itemiterator object at 0x110df59a8>)

然后将该参数传递给 NestedDict() 调用以重建对象。抛出异常是因为 NestedDict 类不接受参数。

您可以在您的子类中覆盖 __reduce__ 方法:

class NestedDict(defaultdict):
def __init__(self):
super().__init__(self.__class__)
def __reduce__(self):
return (type(self), (), None, None, iter(self.items()))

以上生成的元素与 defaultdict.__reduce__() 返回的元素完全相同,只是第二个元素现在是一个空元组。

您也可以只接受并忽略单个参数:

class NestedDict(defaultdict):
def __init__(self, _=None): # accept a factory and ignore it
super().__init__(self.__class__)

_ 名称通常用于表示我忽略此值

另一种实现方式可以是 dict 的子类并提供自定义的 __missing__ method ;为不在字典中的键调用此方法:

class NestedDict(dict):
def __missing__(self, key):
nested = self[key] = type(self)()
return nested
def __repr__(self):
return f'{type(self).__name__}({super().__repr__()})'

这与您的版本完全一样,但不需要额外的 pickle 支持方法:

>>> d = NestedDict()
>>> d['foo']
NestedDict({})
>>> d['foo']['bar']
NestedDict({})
>>> d
NestedDict({'foo': NestedDict({'bar': NestedDict({})})})
>>> pickle.loads(pickle.dumps(d))
NestedDict({'foo': NestedDict({'bar': NestedDict({})})})

关于python - 无法 pickle 递归嵌套的defaultdict,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51991503/

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