AttributeError:无法腌制本地对象 '<locals>.<lambda>'

zur*_*uby 12 python pickle jsonpickle python-3.6 python-3.7

我正在尝试腌制使用以下命令创建的嵌套字典:

collections.defaultdict(lambda: collections.defaultdict(int))
Run Code Online (Sandbox Code Playgroud)

我的简化代码是这样的:

class A:
  def funA(self):
    #create a dictionary and fill with values
    dictionary = collections.defaultdict(lambda: collections.defaultdict(int))
    ...
    #then pickle to save it
    pickle.dump(dictionary, f)
Run Code Online (Sandbox Code Playgroud)

但是它给出了错误:

AttributeError: Can't pickle local object 'A.funA.<locals>.<lambda>'
Run Code Online (Sandbox Code Playgroud)

我打印字典后显示:

defaultdict(<function A.funA.<locals>.<lambda> at 0x7fd569dd07b8> {...}
Run Code Online (Sandbox Code Playgroud)

我尝试在该函数中使字典全局化,但错误是相同的。我很欣赏这个问题的任何解决方案或见解。谢谢!

tde*_*ney 15

pickle记录对函数(模块和函数名称)的引用,而不是函数本身。当 unpickle 时,它​​将加载模块并按名称获取函数。lambda创建没有名称且加载程序无法找到的匿名函数对象。解决方案是切换到命名函数。

def create_int_defaultdict():
    return collections.defaultdict(int)

class A:
  def funA(self):
    #create a dictionary and fill with values
    dictionary = collections.defaultdict(create_int_defaultdict)
    ...
    #then pickle to save it
    pickle.dump(dictionary, f)
Run Code Online (Sandbox Code Playgroud)


ngọ*_*oss 5

正如 @tdlaney 所解释的,lambda创建一个无法被 pickle 的匿名函数。最简洁的解决方案是替换lambdapartial(不需要新函数):

from functools import partial

class A:
  def funA(self):
    #create a dictionary and fill with values
    dictionary = collections.defaultdict(partial(collections.defaultdict, int))
    ...
    #then pickle to save it
    pickle.dump(dictionary, f)
Run Code Online (Sandbox Code Playgroud)