如何pickle和unpickle继承自defaultdict的类的实例?
我有一个继承自 defaultdict
的类,如下所示:
class listdict(defaultdict):
def __init__(self):
defaultdict.__init__(self, list)
我可以pickle它,但是当我取消pickle它时,会发生这种情况:
('__init__() takes exactly 1 argument (2 given)', <class 'listdict'>, (<type 'list'>,))
该类没有定义pickle协议的任何特殊方法。普通 defaultdict(list)
的酸洗和取消酸洗按预期工作。谁能启发我吗?
I have a class that inherits from defaultdict
like this:
class listdict(defaultdict):
def __init__(self):
defaultdict.__init__(self, list)
I can pickle it, but when I unpickle it, this happens:
('__init__() takes exactly 1 argument (2 given)', <class 'listdict'>, (<type 'list'>,))
The class does not define any special methods of the pickle protocol. Pickling and unpickling of a normal defaultdict(list)
works as expected. Can anyone enlighten me?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
类型通过定义一组(相当大的)方法中的一个或多个来定义它的实例如何被腌制。每个人都有自己微妙的行为。请参阅有关 pickle 协议的文档。对于
collections.defaultdict
,它使用__reduce__
方法:元组中的第一项是类型,第二项是要传递的参数的元组实例化时的类型。如果您不覆盖
__reduce__
,第一项将正确更改为您的类型,但第二项不会。这会导致您看到的错误。一个如何修复它的粗略示例:这只是一个粗略示例,因为需要进行酸洗(例如
__reduce_ex__
),而且都相当复杂。在这种情况下,使用__getinitargs__
可能会更方便。或者,您可以使类的
__init__
方法采用可选可调用,默认为list
,或者您可以只使用函数而不是类:Types define how instances of it get pickled by defining one or more of a (fairly large) set of methods. Each has its own subtle behaviour. See the docs on the pickle protocol. In the case of
collections.defaultdict
, it uses the__reduce__
method:The first item in the tuple there is the type, and the second item is the tuple of arguments to pass to the type when instantiating it. If you don't override
__reduce__
, the first item will correctly change to your type, but the second item will not. This causes the error you see. A crude example of how you could fix it:It's only a crude example because there's more to pickling (like
__reduce_ex__
) and it's all fairly intricate. In this case, using__getinitargs__
may be more convenient.Alternatively, you could make your class's
__init__
method take an optional callable, defaulting tolist
, or you could just use a function instead of a class:该错误表明您的“listdict”类应该采用一个参数(隐式自我),但得到了两个参数。
您的类继承自defaultdict,并定义一个初始值设定项。该初始化程序调用 defaultdict 的初始化程序并将“list”传递给它,在本例中它可以是函数或类。 (我懒得去检查)。
您的意思可能是这样做:
现在,当使用给定列表初始化 listdict 时,它将该列表传递给 defaultdict 的构造函数,而不是传递对全局列表的引用。
(也就是说,使用与常见全局方法和类相同的名称(例如“str”、“list”等)被认为是不好的风格,这与您感到困惑的原因相同)。
That error indicates that your 'listdict' class was expected to take one argument (the implicit self), but got two arguments.
Your class inherits from defaultdict, and defines an initializer. This initializer calls defaultdict's initializer and passes 'list' to it, which in this case may be either a function or a class. (I can't be bothered to check).
What you probably meant is to do this:
Now, when listdict is initialised with a given list, it passes THAT list to the defaultdict's constructor, rather than passing a reference to the global list.
(That said, it's considered bad style to use a name that is the same as common global methods and classes, such as 'str', 'list', etc, for the same reason that you got confused).