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

使用命名参数传递default_factory构造defaultdict时触发KeyError问题

为什么用命名参数传递default_factory会让defaultdict抛出KeyError?

这个问题的核心在于**collections.defaultdict的构造函数把default_factory设为了仅限位置参数**,不能通过关键字参数传递。

拆解两种情况的差异:

  • 对于c1 = collections.defaultdict(str):
    这里str是作为第一个位置参数传递给default_factory的,defaultdict正确识别了这个默认工厂函数。当你访问不存在的键c1['new']时,会自动调用str()生成空字符串,所以能正常运行。

  • 对于c2 = collections.defaultdict(default_factory=str):
    defaultdict的__init__方法签名是__init__(self, default_factory=None, /, **kwargs),其中的/是Python的语法标记,表示此符号之前的参数只能用位置传递,不能用关键字参数。所以你写的default_factory=str并没有被赋值给真正的默认工厂属性,而是被当成了一个普通的键值对,存入了字典的初始数据里(相当于给c2初始化了c2['default_factory'] = str)。此时c2的实际default_factory还是默认的None,和普通字典一样,访问不存在的键自然会抛出KeyError。

验证你的猜测:

把你写的测试函数改成仅限位置参数的版本,就能复现同样的问题:

def func(first, /, **kwargs):
    print(f"first参数值: {first}")
    print(f"kwargs内容: {kwargs}")

# 正常运行,first接收位置参数1
func(1)
# 报错!因为first是仅限位置参数,不能用关键字传递
func(first=1)

这和defaultdict的情况完全一致——你以为传递的是构造参数,实际上被当成了字典的初始键值对。

想提升可读性怎么办?

因为default_factory被设计成仅限位置参数,没办法直接用命名参数传递,但可以用两种方式兼顾可读性:

  1. 加注释说明:
c1 = collections.defaultdict(str)  # 默认工厂函数:str,生成空字符串
  1. 自己封装一个小函数,把位置参数转成命名参数:
from collections import defaultdict

def create_defaultdict(default_factory, **initial_data):
    return defaultdict(default_factory, **initial_data)

# 这样就能用命名参数,可读性拉满
c3 = create_defaultdict(default_factory=str)
print(c3['new'])  # 输出空字符串,正常运行

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.26 09:09:55