Why can't pickle dump this instance?

Peter Otten __peter__ at web.de
Fri Aug 13 14:34:29 CEST 2004

Jane Austine wrote:

> class A:
>     def __init__(self,tick):
>         if tick:
>             self.foo=self.bar
>         else:
>             self.foo=self.bur
>     def bar(self):
>         print 'bar'
>     def bur(self):
>         print 'bur'
> import pickle
> pickle.dumps(A())
> running this script results in "TypeError: can't pickle function objects"
> Why does this happen? and what can I do?

By default pickle bypasses the __init__() method completely, it just saves
class name and the instance's __dict__. In your case __dict__ happens to
contain a bound method which cannot be pickled. I don't know why, maybe the
general case where the instance the method is bound to could be a different
object would get too messy.

The normal way to manipulate the state to be pickled/unpickled is to
implement the __getstate__()/__setstate__() pair, but in your case it is
easier to trigger invocation of __init__() by generating the appropriate
argument list via __getinitargs__().


import pickle

class A:
    def __init__(self, tick):
        if tick:
            self.foo = self.bar
            self.foo = self.bur

    def __getstate__(self):
        # copy the __dict__ so that further changes
        # do not affect the current instance
        d = dict(self.__dict__)
        # remove the closure that cannot be pickled
        del d["foo"]
        # return state to be pickled
        return d

    def __getinitargs__(self):
        tick = self.foo == self.bar
        # return argument tuple for __init__()
        # all items must be pickleable
        return (tick,)

    def bar(self):
        print "bar"
    def bur(self):
        print "bur"

if __name__ == "__main__":
    # test it
    for tick in [False, True]:
        print "\ntick =", tick
        a = A(tick)
        s = pickle.dumps(a)
        b = pickle.loads(s)

More information about the Python-list mailing list