Словарь __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