Python函数重复调用时返回不同的结果

4
当我运行下面的Python代码时,
def main():
    #print prime_factors(10)
    print prime_factors(9)

def prime_factors(n, i=2, factors=[]):
    if n==1:
        return factors
    if(n%i==0):
        factors.append(i)
        n = n/i
        return prime_factors(n, i, factors)
    else:
        return prime_factors(n, i+1, factors)

if __name__ == '__main__':
    main()

该程序返回预期结果,即9的质因数:

[3, 3]

如果我从第2行的注释中删除"print prime_factors(10)",会发生奇怪的事情。 对于10来说一切都好,但是对于9来说,它不仅包含了9的质因数,还包括10的质因数:
[2, 5]
[2, 5, 3, 3]

如果我使用两个可选参数调用该函数。
def main():
    print prime_factors(10, i=2, factors[])
    print prime_factors(9, i=2, factors[])

一切正常运作良好。

[2,5]
[3,3]

我无法弄清楚原因。我怀疑这是某个作用域的问题,但我就是不理解 :-( 任何帮助将不胜感激。


“Python中的最小惊奇:可变默认参数”绝对是Python问题重复闭包的头号原因... - Bakuriu
1
@AshwiniChaudhary:这是一个重复的问题,但新用户如何从标题中知道呢? - Jace Browning
2
@JaceBrowning 但是那些知道的人可以将其标记为重复。没有必要一遍又一遍地回答相同的问题。 - Ashwini Chaudhary
1
搜索“[python]默认值更改”会将该问题作为第4个结果返回(至少对我来说是这样)。 - Bakuriu
4个回答

7
默认情况下,函数参数的定义值是“粘性”的 - 它们属于函数体本身,因此当您修改它们时,它们会保持修改状态,以备下一次调用使用。

4
这是因为factors是可变的默认参数。只有在第一次调用时会计算出一个名为factors的新列表,因此如果您改变了该列表,则在后续的调用中会得到已改变的列表。请参见以下代码片段 -
>>> def test(a = []):
        a.append('x')
        return a

>>> test()
['x']
>>> test()
['x', 'x']

尝试将其默认初始化为 None,然后在函数体内检查 None 并分配一个空列表。
>>> def test(a = None):
        if a is None:
            a = []
        a.append('x')
        return a

>>> test()
['x']
>>> test()
['x']

0
在函数参数中将factors=[]设置为默认值并不是一个好主意。Python只在第一次遇到函数定义时评估[]表达式。基本上这意味着您对prime_factors的所有调用都将使用相同的列表,并且每个调用都将附加自己的值。
例如:
prime_factors(9)
prime_factors(9)
prime_factors(9)

将返回

[3,3,3,3,3,3]

0

请参考这个问题:{{link1:“最小惊奇”和可变默认参数}}

你想要做类似于以下的事情:

...
def prime_factors(n, i=2, factors=None):
    if factors is None:
        factors = [] 
    ...

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接