字典__new__调用带有unpickled参数的问题

时间:2014-06-05 22:59:24

标签: python class dictionary pickle

所以我尝试创建dict的子类,使其成为1)不可变的,2)接受pickle数据,但是当它应该取消数据时,它会因错误而失败:TypeError: cannot convert dictionary update sequence element #0 to a sequence

这是我的代码:

>>> class Message(dict):   
        def __new__(cls, *args, **kwargs):
            """Create a new message object."""
            if len(args) == 1 and isinstance(args[0], bytes):
                args = (pickle.loads(args[0]),)
            return super().__new__(cls, *args, **kwargs)

>>> Message({"a": 1})
{'a': 1}
>>> Message(pickle.dumps({"a": 1}))
Traceback (most recent call last):
  File "<pyshell#99>", line 1, in <module>
    Message(pickle.dumps({"a": 1}))
TypeError: cannot convert dictionary update sequence element #0 to a sequence

修改

我把它改为:

def __new__(cls, *args, **kwargs):
    """Create a new message object."""
    if len(args) == 1 and isinstance(args[0], bytes):
        args = (pickle.loads(args[0]),)
    self = super().__new__(cls)
    self.__init__(*args, **kwargs)
    return self

但它仍然不起作用,所以__new__ - &gt; __init__也没有帮助。

1 个答案:

答案 0 :(得分:0)

您得到的错误是因为dict.__new__没有按照您的想法行事;它总是返回一个新的空字典。

然后将参数传递给dict.__init__,它将根据其参数更新self(我们的dict子类)。

所以,唉,你做不到dict(pickle.dumps({'a':1})

作为一种解决方法,您可以在super().update()中致电__new__,并提供无操作__init__,但我不会这样做。也许你真正想要的只是pickle.loads(...)而不是MyFancySubclass(pickle.loads(...));

编辑 ,因为它显然不清楚,您的子类必须如下所示:

class MyDict(dict):
    def __init__(self, *args, **kwargs):
        pass # DO NOTHING!

    def __new__(cls, *args, **kwargs):
        self = super().__new__(cls)
        self.update(get_some_data(args, kwargs))  # NOT __init__
        return self