如何腌制和释放从defaultdict继承的类的实例? [英] How to pickle and unpickle instances of a class that inherits from defaultdict?

查看:70
本文介绍了如何腌制和释放从defaultdict继承的类的实例?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个从defaultdict继承的类,如下所示:

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'>,))

该类未定义pickle协议的任何特殊方法.正常的defaultdict(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?

推荐答案

类型通过定义一组(相当大的)方法中的一个或多个来定义如何腌制它的实例.每个都有自己的微妙行为.请参见有关泡菜协议的文档.对于collections.defaultdict,它使用__reduce__方法:

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:

>>> l = collections.defaultdict(list)
>>> l.__reduce__()
(<type 'collections.defaultdict'>, (<type 'list'>,), None, None, <dictionary-itemiterator object at 0x7f031fb3c470>)

元组中的第一项是类型,第二项是在实例化时传递给该类型的参数的元组.如果您不覆盖__reduce__,则第一项将正确更改为您的类型,但第二项则不会.这将导致您看到的错误.有关如何解决此问题的粗略示例:

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:

>>> import collections
>>> import pickle
>>> class C(collections.defaultdict):
...     def __init__(self):
...         collections.defaultdict.__init__(self, list)
...     def __reduce__(self):
...         t = collections.defaultdict.__reduce__(self)
...         return (t[0], ()) + t[2:]
...
>>> c = C()
>>> c[1].append(2)
>>> c[2].append(3)
>>> c2 = pickle.loads(pickle.dumps(c))
>>> c2 == c
True

这只是一个粗略的例子,因为酸洗还有很多(例如__reduce_ex__),而且都很复杂.在这种情况下,使用__getinitargs__可能会更方便.

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.

或者,您可以使类的__init__方法采用可调用的可选,默认为list,或者可以使用函数代替类:

Alternatively, you could make your class's __init__ method take an optional callable, defaulting to list, or you could just use a function instead of a class:

def listdict():
    return collections.defaultdict(list)

这篇关于如何腌制和释放从defaultdict继承的类的实例?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆