You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用dill序列化含lambda默认值的defaultdict时遇NameError问题

问题原因分析

你遇到的问题本质是lambda函数的闭包变量没有被dill正确序列化到目标环境。你的lambda: default_value依赖了外部定义的default_value变量,dill在序列化这个lambda时,只是保存了lambda的代码逻辑,但并没有把default_value这个变量的内容一起打包到序列化文件里。当你在另一个脚本加载后访问新键时,lambda试图去当前环境找default_value,但这个变量在新脚本里根本没定义,所以就抛出了NameError。

解决方案

这里有几种可行的解决办法,按简单程度排序:

1. 直接把默认值内联到lambda中

最直接的方式是避免lambda依赖外部变量,把default_value的计算结果直接写进lambda里:

# 序列化脚本中修改这一行
dict_with_default = defaultdict(lambda: 0.5)  # 因为a/b=1/2=0.5

这样lambda不再依赖任何外部变量,序列化和反序列化后,访问新键时能直接返回0.5,不会有变量找不到的问题。

2. 使用functools.partial绑定默认值

如果你的默认值是动态计算的,不想硬编码,可以用functools.partial来创建一个绑定了默认值的函数,它比lambda更容易被序列化且不依赖外部变量:

import dill
from collections import defaultdict
from functools import partial

a = 1
b = 2
default_value = a/b
# 用partial创建一个返回default_value的函数
default_func = partial(lambda x: x, default_value)
dict_with_default = defaultdict(default_func)

# 后续的序列化代码不变
dict_with_default['a'] = 1.2
dict_with_default['b'] = 3.5
dict_with_default['c'] = 0.25

with open('./pickles/simple_dict_dill.p', 'wb') as file:
    dill.dump(dict_with_default, file, protocol=dill.HIGHEST_PROTOCOL)

这样default_func已经把default_value的值绑定在了函数内部,反序列化后不需要外部环境有这个变量就能正常工作。

3. 让dill递归序列化闭包变量

dill其实支持序列化闭包变量,但需要开启递归序列化的设置。你可以在序列化前添加这一行:

dill.settings['recurse'] = True

完整的序列化代码:

import dill
from collections import defaultdict

dill.settings['recurse'] = True  # 开启递归序列化闭包

a = 1
b = 2
default_value = a/b
dict_with_default = defaultdict(lambda: default_value)
dict_with_default['a'] = 1.2
dict_with_default['b'] = 3.5
dict_with_default['c'] = 0.25

with open('./pickles/simple_dict_dill.p', 'wb') as file:
    dill.dump(dict_with_default, file, protocol=dill.HIGHEST_PROTOCOL)

这样dill会把lambda依赖的default_value也一起序列化到文件里,反序列化后就能正常访问新键了。

验证测试

在加载脚本中执行以下代码,三种方案都能正常输出:

import dill
with open('./pickles/simple_dict_dill.p', 'rb') as file:
    simple_dict_dill = dill.load(file)
print("a:", simple_dict_dill['a'])  # 输出1.2
print("d:", simple_dict_dill['d'])  # 输出0.5
print("e:", simple_dict_dill['e'])  # 输出0.5,不再报错

内容的提问来源于stack exchange,提问作者balkon16

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 06:32:17