Why can't you pickle instancemethods?
Chris
chrisspen at gmail.com
Fri Oct 20 19:58:22 EDT 2006
mdsteele at gmail.com wrote:
> Chris wrote:
> > Why can pickle serialize references to functions, but not methods?
> >
> > Pickling a function serializes the function name, but pickling a
> > staticmethod, classmethod, or instancemethod generates an error. In
> > these cases, pickle knows the instance or class, and the method, so
> > what's the problem? Pickle doesn't serialize code objects, so why can't
> > it serialize the name as it does for functions? Is this one of those
> > features that's feasible, but not useful, so no one's ever gotten
> > around to implementing it?
>
> I have often wondered this myself. I'm convinced that it would in fact
> be useful -- more than once I've written a program that has lots of
> objects with function pointers, and where it was inconvenient that the
> method pointers could not be pickled. One compromise that I have used
> before is to write a class such as:
>
> class InstanceMethodSet(object):
> def __init__(self,methods):
> self.methods = set(methods)
> def __getstate__(self):
> return [(method.im_self, method.im_func.func_name)
> for method in self.method]
> def __setstate__(self,state):
> self.methods = set(getattr(obj,name) for obj,name in state)
>
> Obviously, this particular example is crude and not terribly robust,
> but it seems to do the job -- it effectively lets you pickle a set of
> instance method pointers. I don't know of any reason why instance
> methods (or class or static methods) couldn't be pickled directly,
> unless perhaps there exists some kind of pathological corner case that
> would create Badness?
>
> -Matt
Thanks, that's quite clever. Although I think you'd still have to
explicitly specify im_self for staticmethods. I could imagine a similar
callable proxy that simply removes the direct method reference from the
equation:
class MethodProxy(object):
def __init__(self, obj, method):
self.obj = obj
if isinstance(method, basestring):
self.methodName = method
else:
assert callable(method)
self.methodName = method.func_name
def __call__(self, *args, **kwargs):
return getattr(self.obj, self.methodName)(*args, **kwargs)
picklableMethod = MethodProxy(someObj, someObj.method)
More information about the Python-list
mailing list