Python中递归函数默认参数的使用问题请教

想写一个递归,能够“融化”一个 list。比如[1,[2,3]]变成[1,2,3]。 完成代码如下:

def list_melt(lst, new_lst=[]):
    for element in lst:
        if not isinstance(element, (tuple,list)):
            new_lst.append(element)
        else:
            list_melt(element, new_lst)
    return new_lst

测试结果是,第一次使用这个函数可以得到想要的结果,但第二次开始结果会被叠加,也就是默认的 new_lst 参数会跟在上一次测试的结果后面。 比如说,第一次传入[1,[2,3]]变成[1,2,3],第二次传入[[4,5],6]会变成[1,2,3,4,5,6]。请问为什么默认参数会失效?谢谢。


Python中递归函数默认参数的使用问题请教

3 回复

我遇到过这个问题,典型的Python陷阱。递归函数里用可变对象(比如列表)做默认参数,所有递归调用共享同一个列表实例。

看这个例子:

def bad_recursion(n, result=[]):
    if n <= 0:
        return result
    result.append(n)
    return bad_recursion(n-1)

print(bad_recursion(3))  # 第一次调用正常:[3, 2, 1]
print(bad_recursion(2))  # 问题来了:[3, 2, 1, 2, 1]

问题在于result=[]只在函数定义时创建一次,后续调用都复用这个列表。正确做法是用None做默认值,在函数内部初始化:

def good_recursion(n, result=None):
    if result is None:
        result = []
    if n <= 0:
        return result
    result.append(n)
    return good_recursion(n-1, result)

print(good_recursion(3))  # [3, 2, 1]
print(good_recursion(2))  # [2, 1] 这次正常了

简单说就是:递归函数别用可变对象当默认参数。


python 里面的经典误区之一,默认参数不能是可变类型,因为默认参数只在函数定义时注册一次。具体可以问谷歌

解释得很清楚了,非常感谢!

回到顶部