knub
knub

Reputation: 4032

Pickle doesn't work for class inherited from "namedtuple" when overriding "__new__"

The following code fails

from collections import namedtuple
import pickle

class Foo(namedtuple("_Foo", ["a", "b"])):
    def __new__(cls, **kwargs):
        self = super().__new__(cls, **kwargs)
        # some custom code
        return self

foo = Foo(a=1, b=2)
pickle.loads(pickle.dumps(foo))

with

Traceback (most recent call last):
  File "bar.py", line 10, in <module>
    pickle.loads(pickle.dumps(foo))
TypeError: __new__() takes 1 positional argument but 3 were given

It works if I remove the new __new__ implementation, but I want to have some custom code there. How do I need to change the implementation of __new__ to not have the error?

I'm running Python 3.5.

Upvotes: 0

Views: 115

Answers (1)

gmds
gmds

Reputation: 19885

The reason is quite simple; in general, the C API passes stuff around as positional parameters, instead of named parameters. Therefore, you just need to provide for this with *args:

from collections import namedtuple
import pickle

class Foo(namedtuple("_Foo", ["a", "b"])):
    def __new__(cls, *args, **kwargs):
        self = super().__new__(cls, *args, **kwargs)
        # some custom code
        return self

foo = Foo(a=1, b=2)
pickle.loads(pickle.dumps(foo))

Upvotes: 2

Related Questions