首页 > 解决方案 > 这个函数变量如何持续到 Python 中的下一次调用?

问题描述

如果我运行这段代码,我希望看到 [0] 返回两次。相反,我看到 [0,1]。

def append(flist=[]):
    # append the length of a list to the list
    flist.append(len(flist))
    return flist

print(append())
print(append())

为什么会这样?不应该因为范围而重置表达式吗?如果 flist 存在于函数之外,我如何访问它?

此示例来自https://www.toptal.com/python#hiring-guide关于问题“Q:下面的第二个 append() 语句将打印出什么?”。它确实包含一个简短的解释,但我不明白这是怎么可能的。我能想到的任何分析记忆的东西都没有向我展示这些值,但我也不确定什么是正确的工具来解决这个问题。查看诸如 locals() 或 dir() 之类的东西似乎没有任何意义。

标签: pythonpython-3.x

解决方案


如果您尝试这样做,像 PyCharm 这样的编辑器实际上会警告您。

Pycharm 说:“默认参数值是可变的。”

这就是问题所在:您提供的默认值(空列表)是一个实际列表,并且像任何其他列表一样,您可以更改它,如果多个变量将该列表作为值,这些更改将显示在所有他们。

因此,要修复该代码(并获得您想要的行为),您可以这样做:

def append(flist=None):
    # initialise if needed
    if flist is None:
        flist = []
    # append the length of a list to the list
    flist.append(len(flist))
    return flist

print(append())
print(append())

这为您提供了预期的行为,因为对于两个调用,都没有传递任何列表,所以 flist 是 None 并且在每次传递时都分配一个新的空列表,而不是两次传递初始默认列表(第一次运行时为空,包含0在第二个)。

正如原始问题中所建议的那样,该功能的范围append不会持续存在。相反,默认值与函数定义存在于同一范围内。因此,在这种情况下,在全局范围内。

每当调用该函数时,这个全局定义的列表就会被修改,这就是为什么这个预期范围为函数的值仍然存在的原因。


推荐阅读