Python默认参数求值

3
我是一个有用的助手,可以为您翻译文本。
我正在阅读Python Documentation Release 2.7.10中的Python教程,遇到了这样的内容。
代码
def fun1(a,L=[]):
    L.append(a)
    return L

print fun1(1)
print fun1(2)
print fun1(3)

def fun2(a,L = None):
    if L is None:
        L=[]
    L.append(a)
    return L

print fun2(1)
print fun2(2)
print fun2(3)

输出

[1]
[1, 2]
[1, 2, 3]
[1]
[2]
[3]

Process finished with exit code 0

如果第一个函数fun1()中的L=[]只被调用一次,那么fun1()的输出就很好。但是为什么fun2()中每次都会调用L=None呢?

为什么L=None不会在每次调用时被执行?- 我不知道你想表达什么意思。 - deceze
我假设 L=None 每次都被调用/执行。这就是为什么第二个函数 fun2() 中的条件 if L is None 每次都为真的原因。 - Nitin Pandey
1
默认参数在函数声明时被计算。空列表是可变的,因此在每个函数调用中,您都在编辑同一个列表。向其附加不会创建新对象。使用None,在函数体中创建列表。每次从函数返回新列表。 - Łukasz Rogalski
3个回答

4
在函数声明中,L=[] 使Python本质上执行以下操作:
  • 此函数有一个名为L的参数
  • 它的默认参数是[],让我们将这个特定的[]放在一边,任何时候都使用它,如果没有传递L参数
  • 每次调用函数时,创建一个名为L的变量,并将其分配给传递的参数或我们之前设置的值
因此,[]部分只执行一次,创建一个列表对象,将其设置在一旁并保留,这就是为什么如果您修改它,它会累积变化。完全相同的事情也发生在None上,然而None没有被修改也不可变,所以你不会看到任何奇怪的副作用。None仍然只被“执行”一次,那个特定的None值和列表一样被设置在一边,只是你没有对None值本身做任何事情。

但是在fun2()内部的if条件语句中,我将L=None更改为L=[]。为什么这个赋值/更改不是永久性的或在其他后续函数调用中可见的呢? - Nitin Pandey
每次调用该函数时,都会创建并分配一个值给变量 L。值 [] 是永久的,而不是它与 L 的关联。值 [] 存储你向其 .append 的内容,而不是 L。内存中的永久对象 [] 与指向它的变量 L 是不同的。 - deceze

2
当你定义一个函数时,默认参数的值会被计算,但是函数体只会被编译。你可以通过属性检查函数定义的结果。其中包含默认值的__defaults__属性和包含函数体的__code__属性(这些在定义函数时创建)。
第二个例子中的情况是,在函数定义时'None'被计算(显然它会计算为'None'!),但有条件地将'[]'分配给'L'的代码只被编译,并且每次都运行(条件符合)。

1

默认参数只被评估一次。在 fun1 中,您有相同的列表,您不断地将其添加到其中。在 fun2 中,您将一个新的 [] 赋给参数,然后附加到它。像任何分配一样,它的范围将限于它发生的块。


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