内存中的默认函数值和变量

时间:2019-04-20 01:50:08

标签: python-3.x

我遇到了以下代码:

def f(x,l=[]):
for i in range(x):
    l.append(i*i)
print(l) 

f(2)
f(3,[3,2,1])
f(3)

返回:

[0, 1]
[3, 2, 1, 0, 1, 4]
[0, 1, 0, 1, 4]

我的问题是这个

为什么在第三个函数调用f(3)中,我不被l=[]中的def (f(x,l=[])覆盖,然后返回[0,1,4]?这是怎么回事?

当我这样做时,事情按预期进行。.

l=[]
[l.append(i*i) for i in range(2)]
print(l)
l=[1, 2, 3]
[l.append(i*i) for i in range(3)]
print(l)
l=[]
[l.append(i*i) for i in range(3)]
print(l)

打印:

[0, 1]
[1, 2, 3, 0, 1, 4]
[0, 1, 4]

我知道答案与python将数据存储在内存中的方式有​​关,但是即使用id(l)探索(打印出与l相同的ID, f(2)f(3)都使用,但是f(3, [3,2,1])的ID不同。

谢谢您的见解!

1 个答案:

答案 0 :(得分:0)

执行此操作的正确方法是在函数内部使用局部变量lst,该变量负责您在函数内部进行的操作,而不是像这样对要传递的变量进行操作。

def f(x,lst=None):
    lst = lst or []
    for i in range(x):
        lst.append(i*i)
    print(lst)

f(2)
f(3,[3,2,1])
f(3)

哪个给您输出为

[0, 1]
[3, 2, 1, 0, 1, 4]
[0, 1, 4]

前一种方法不起作用的原因是,当在参数的默认值中检测到可变值(如列表或字典)时,它们在函数定义时仅被评估一次,这意味着修改的默认值。该参数将影响该函数的所有后续调用。
但是在更改的函数中,我正在制作一个新的局部变量以在列表上进行操作,该变量是传递的参数的副本,因此在这里我们不会遇到此问题。