One can use the wonderful dill
package to pickle lambda functions (amongst others). See this post. Here though, I'd like to dynamically transform lambda functions into object that are functionally equivalent, but are builtin-picklable. (I can give more context if necessary.)
I came up with the following, but my way of extracting code from a lambda function is fragile, and reconstructing the function using eval
is scary (but should it be, given one should only unpickle data one trusts anyway -- see pickle module's warning).
import inspect, pickle
# TODO: Fragile. Make more robust.
def lambda_code(lambda_func):
func_str = str(inspect.getsourcelines(lambda_func)[0])
return func_str.strip("['\\n']").split(" = ")[1]
class PicklableLambda:
def __init__(self, lambda_func):
self.func = lambda_func
self.__signature__ = inspect.signature(self.func)
def __getstate__(self):
return lambda_code(self.func)
def __setstate__(self, func_code):
func = eval(func_code) # scary?
self.__init__(func)
def __call__(self, *args, **kwargs):
return self.func(*args, **kwargs)
f = lambda x, y=0: x + y
ff = PicklableLambda(f)
fff = pickle.loads(pickle.dumps(ff))
assert fff(2, 3) == ff(2, 3) == f(2, 3)