读配置时,settings.get('timeout') 返回 None,你能确定配置里没有 timeout 这个键吗?不能:它也可能存在,只是值被明确设成了 None。这两个状态看起来一样,后续处理却可能完全不同。
一个最小实验:两个字典,结果相同
settings = {'timeout': None}
missing = {}
print(settings.get('timeout')) # None
print(missing.get('timeout')) # None
print('timeout' in settings) # True
print('timeout' in missing) # False
本次在 Python 3.14.7 中实际运行了这段合成数据实验。get() 默认在键不存在时返回 None;但如果键存在,返回的就是该键对应的值。因此,单看结果是否为 None,不足以判断键是否缺失。Python 官方字典文档也把“键不存在时返回默认值”和“键存在时返回对应值”区分开来。
只关心有没有这个键:用成员检查
if 'timeout' in settings:
value = settings['timeout'] # 即使 value 是 None,也表示键已提供
else:
value = 30 # 仅在键缺失时使用默认值
这种写法适合“调用方是否明确提供了这个配置”本身有意义的场景。它不会把 None、0、False 或空字符串都当成缺失。别用 if settings.get('timeout') 代替成员检查:那会把多个合法的假值混在一起。
需要一次取值:给缺失状态一个专用标记
MISSING = object()
value = settings.get('timeout', MISSING)
if value is MISSING:
print('没有提供 timeout')
elif value is None:
print('明确设置为 None')
else:
print('实际值:', value)
实验中,两个字典的 get() 默认调用都得到 None;传入专用哨兵后,只有缺键的字典返回哨兵。这里要用独一无二的对象比较身份,不能随手选一个可能本来就是有效配置值的字符串。若函数多处共享这个标记,把它定义在清楚的作用域,并避免把它泄漏为用户可配置值。
别把“缺失”规则误写成“空值”规则
有些配置约定确实规定 None 与没写相同;那就应明确写出并测试这条约定。另一些场景把 None 当成显式关闭或交由上层决定。字典本身不会替你选择业务含义。
最小测试可以同时覆盖:键不存在、键存在且值为 None、键存在且值为 0 或 False。先确定这几种输入各自应得到什么,再决定用 in、哨兵,还是有意把空值归并到默认值。
这篇小实验只验证 Python 字典取值行为,没有涉及某个线上配置系统,也没有证明性能或生产问题已经修复。结论很窄:如果“没提供”和“明确提供了 None”需要区别,就不要只看 get() 的返回值;把缺失状态单独表达出来。
本文由作者组织的小型合成数据实验与 AI 辅助整理而成。实验环境为 Python 3.14.7,核对日期为 2026 年 10 月 16 日。参考:Python 官方字典类型文档。