Hello, Zaur Shibzoukhov wrote: > This is a case: > > class C(object): > def __new__(cls, *, b): > inst = super().__new__(cls) > inst.b = b > return inst > >>>> c = C(b=17) >>>> image = pickle.dumps(c, protocol=3) >>>> c = pickle.loads(image) > Traceback (most recent call last): > File "test_new.py", line 17, in <module> > c = pickle.loads(image) > File "D:\Python30\lib\pickle.py", line 1329, in loads > return Unpickler(file, encoding=encoding, errors=errors).load() > TypeError: __new__() needs keyword-only argument b > > Do we need to improve pickle protocol in order to allow instance > creation functions get keyword arguments too?
Note that you have a similar error even when the argument is a regular one: class C(object): def __new__(cls, b): inst = super().__new__(cls) inst.b = b return inst >>> c = C(b=17) >>> image = pickle.dumps(c, protocol=3) >>> c = pickle.loads(image) Traceback (most recent call last): File "c:\temp\t.py", line 11, in <module> c = pickle.loads(image) File "c:\Python30\lib\pickle.py", line 1329, in loads return Unpickler(file, encoding=encoding, errors=errors).load() TypeError: __new__() takes exactly 2 positional arguments (1 given) A __getnewargs__ method is needed. In this case, it should return (self.b,). Now, I would like to translate your question to "Is there an equivalent of __getnewargs__ that can pass keyword arguments to __new__?". The only solution I could find involves a global factory function that calls the constructor, but does not use keyword arguments: class C(object): def __new__(cls, *, b): inst = super(C, cls).__new__(cls) inst.b = b return inst def __reduce__(self): return build_C, (self.b,) def build_C(b): return C(b=b) Is there a more object-oriented way? -- Amaury Forgeot d'Arc _______________________________________________ Python-3000 mailing list Python-3000@python.org http://mail.python.org/mailman/listinfo/python-3000 Unsubscribe: http://mail.python.org/mailman/options/python-3000/archive%40mail-archive.com