在函数调用之间保存本地对象值(可能是范围误解)

Local object value is being saved between function calls (maybe scopes misunderstanding)

我在尝试解决 "flattening" 列表列表的任务时感到困惑。
例如,我有一个列表 [1, [2, 2, 2], 4] - 我需要将其转换为 [1, 2, 2, 2, 4]。
我解决了它方式:

def flat_list(array, temp_list=[]):
    for item in array:
        if str(item).isdigit():
            temp_list.append(item)
        else:
            temp_list = flat_list(item, temp_list)

    return temp_list

但是当我测试它时:

assert flat_list([1, 2, 3]) == [1, 2, 3]
assert flat_list([1, [2, 2, 2], 4]) == [1, 2, 2, 2, 4]
assert flat_list([[[2]], [4, [5, 6, [6], 6, 6, 6], 7]]) == [2, 4, 5, 6, 6, 6, 6, 6, 7]

"temp_list" 的值正在函数调用之间传输。第二个断言开头的 "temp_list" 的值是 [1, 2, 3] - 第一个断言的 "return" 的值 - 但不是“[]”.

我猜,这是因为我对范围和 "return" 指令有一些误解,但我不明白到底是什么。

这是 Python 中的一个已知问题。

Default parameter values are always evaluated when, and only when, the “def” statement they belong to is executed

参考:http://effbot.org/zone/default-values.htm

在您的代码示例中,temp_list 的默认值在执行 def 语句时计算。因此它被设置为一个空列表。在随后的调用中,列表不断增长,因为不再评估 temp_list 的默认值,并且它继续使用它第一次创建的列表实例。

这可能是一个解决方法:

def flat_list(array, temp_list=None):
    if not temp_list:
         temp_list = []

    for item in array:
        if str(item).isdigit():
            temp_list.append(item)
        else:
            temp_list = flat_list(item, temp_list)

    return temp_list

这里,我们传递了None而不是空列表。然后在函数体内我们检查值并根据需要初始化一个空列表。