2016-01-06 34 views
1

是否有一个函数或类能够将lambda函数作为参数并返回可以使用Pickle进行pickle的对象或函数?将lambda函数转换为pickleable对象

我想并行使用joblib.Parallel有一个lambda函数的问题,并将所有lambda函数转换为命名函数的代码,使我的代码看起来比以前更糟糕。

回答

2

注意,酸洗的功能仅仅是泡菜它的名字和模块的名称定义它:

In [16]: import pickle 

In [19]: def foo(x): return x+1 

In [20]: pickle.dumps(foo) 
Out[20]: 'c__main__\nfoo\np0\n.' 

所以咸菜功能你需要给它一个名字。取消该功能需要导入模块。

如果将所有lambda函数命名为“使代码更糟糕”,那么可能将它们隐藏在单独的模块中,或者考虑如何将函数泛化以减少它们的数量。

+0

我试图避免对代码进行重大更改,除非绝对必要。我发现lambda函数非常有用,并且将它们命名并将它们移到不同的模块中,这似乎是一个笨拙的解决方案。 – BoZenKhaa

1

您可以使用dill而不是pickle,它知道如何序列化lambda,即使在函数或类中用作默认参数时也是如此。

>>> import dill 
>>> 
>>> def doit(x, y=lambda x:x+1): 
... return y(x) 
... 
>>> doit(3) 
4 
>>> _ = dill.dumps(doit) 
>>> _ 
'\x80\x02cdill.dill\n_create_function\nq\x00(cdill.dill\n_load_type\nq\x01U\x08CodeTypeq\x02\x85q\x03Rq\x04(K\x02K\x02K\x02KCU\n|\x01\x00|\x00\x00\x83\x01\x00Sq\x05N\x85q\x06)U\x01xq\x07U\x01yq\x08\x86q\tU\x07<stdin>q\nU\x04doitq\x0bK\x01U\x02\x00\x01q\x0c))tq\rRq\x0ec__builtin__\n__main__\nh\x0bh\x00(h\x04(K\x01K\x01K\x02KCU\x08|\x00\x00d\x01\x00\x17Sq\x0fNK\x01\x86q\x10)h\x07\x85q\x11U\x07<stdin>q\x12U\x08<lambda>q\x13K\x01U\x00q\x14))tq\x15Rq\x16c__builtin__\n__main__\nh\x13NN}q\x17tq\x18Rq\x19\x85q\x1aN}q\x1btq\x1cRq\x1d.' 
>>> didit = dill.loads(_) 
>>> didit(3) 
4 
>>> 

注意,还嵌套lambda表达式和关闭工作了就好了:

>>> f = lambda x: lambda y: x+y 
>>> f(1)(2) 
3 
>>> dill.loads(dill.dumps(f))(1)(2) 
3 
>>> dill.loads(dill.dumps(f(1)))(2) 
3 
>>> 

我知道有至少joblib一个分支,使用dill代替pickle,这可能是为什么你问首先是pickle。如果找不到分支,请使用与dill相似的cloudpickle,并且这也可能有效。

+0

我没有意识到有这样的分支,我会研究一下! – BoZenKhaa