Python:pickling嵌套函数

Max*_*sin 9 python nested function pickle

使用示例

def foo(a):
    def bar(b):
        return a+b
    return bar

d = {1:foo(1), 2:foo(2)}
Run Code Online (Sandbox Code Playgroud)

看来pickle模块不能使用未在模块范围定义的函数,因此酸洗'd'将不起作用.我还应该考虑另一种酸洗机制吗?

Blc*_*ght 14

我担心你不能腌制嵌套函数.

pickle模块按名称序列化功能.也就是说,如果你myfunc在一个模块中有一个函数,mymodule它只是保存名称mymodule.myfunc并在反序列化时再次查找它.(这是一个重要的安全性和兼容性问题,因为它保证了反序列化代码使用自己的函数定义,而不是可能被破坏或过时的原始定义.)

唉,pickle不能用嵌套函数做到这一点,因为无法通过名称直接解决它们.bar例如,您的功能无法从外部访问foo.

如果你需要一个像函数一样工作的可序列化对象,你可以用一个__call__方法创建一个类:

class foo(object):
    def __init__(self, a):
        self.a = a
    def __call__(self, b): # the function formerly known as "bar"
        return self.a + b
Run Code Online (Sandbox Code Playgroud)

这就像问题中的嵌套函数一样,并且应该没有问题pickle.但请注意,在反序列化foo实例时,您需要具有相同的类定义.


Mik*_*rns 5

如果您使用dill代替,则可以腌制嵌套函数pickle

>>> import dill
>>>    
>>> def foo(a):
...   def bar(b):
...     return a+b
...   return bar
... 
>>> d = {1:foo(1), 2:foo(2)}
>>> 
>>> _d = dill.dumps(d)
>>> d_ = dill.loads(_d)
>>> d_
{1: <function bar at 0x108cfe848>, 2: <function bar at 0x108cfe8c0>}
>>> d[1](0) + d[2](10)
13
>>> 
Run Code Online (Sandbox Code Playgroud)