为何递归函数的默认字典参数在多次调用时未重置?
递归创建频率字典时默认参数异常问题
尝试通过递归实现字符频率统计字典,将空字典设为函数的默认参数,但连续调用该函数定义两个变量时,第二次调用的字典初始值并非空字典,导致结果不符合预期。
问题代码
def freq_dict(list1, a={}): if len(list1)>0: char1= list1[0] if char1 in a.keys(): a[char1]+=1 n=a.copy() list1=list1[1:] return freq_dict(list1, n) else: a[char1]=1 n=a.copy() list1=list1[1:] return freq_dict(list1, n) else: return a a=freq_dict([1, 2, 2, 1]) b=freq_dict([1, 2, 2, 1]) print(a) print(b)
预期输出
{1: 2, 2: 2} {1: 2, 2: 2}
实际问题
第一次调用函数时结果符合预期,但第二次调用时,函数的默认字典初始值变为{1:1},导致最终输出结果异常。
原因分析
Python中可变类型的默认参数只会在函数定义时初始化一次,而非每次调用函数时重新创建。字典是可变对象,第一次调用函数时,直接修改了默认参数对应的字典对象(a[char1]=1),这个修改会被永久保留,导致后续调用时默认参数不再是空字典。
解决方案
不要用可变对象作为默认参数,而是将默认参数设为None,在函数内部判断并初始化空字典:
def freq_dict(list1, a=None): # 每次调用时初始化空字典,避免默认参数复用 if a is None: a = {} if len(list1) > 0: char1 = list1[0] if char1 in a: a[char1] += 1 else: a[char1] = 1 # 递归时传递当前字典的副本,避免修改原字典 return freq_dict(list1[1:], a.copy()) else: return a a=freq_dict([1, 2, 2, 1]) b=freq_dict([1, 2, 2, 1]) print(a) print(b)
说明
- 将默认参数改为
None,每次调用函数时都会在内部重新创建空字典,彻底避免了默认参数的复用问题。 - 简化了原代码逻辑,去掉重复的列表赋值操作,直接用
list1[1:]传递剩余元素。
内容的提问来源于stack exchange,提问作者Arsh Kulshrestha
相关产品推荐
相关产品推荐

