Словарь __new__ вызов проблемы с непроверенным аргументом

Поэтому я попытался создать подкласс dict чтобы сделать его 1) неизменным и 2) принимать маринованные данные, но когда предполагается, что данные будут извлечены, произойдет сбой с ошибкой: 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__ -> __init__ тоже не помогло.

1 ответ

Ошибка, которую вы получаете, потому что 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
Другие вопросы по тегам