Python默认参数求值

Python默认参数求值,python,python-2.7,arguments,default-arguments,Python,Python 2.7,Arguments,Default Arguments,我正在阅读python文档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

我正在阅读python文档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
,默认参数只计算一次。在
fun1
中,您的列表与您一直添加到的列表相同。在
fun2
中,为参数指定一个新的
[]
,然后将其追加。与任何赋值一样,它的范围将限于它发生在的块。

定义函数时,默认参数的值将被计算,函数体只会被编译。您可以通过属性检查函数定义的结果。有一个
\uuuuu defaults\uuuuuu
属性包含默认值,还有一个
\uuuuuuu code\uuuuu
属性包含主体(因此这些属性是在定义函数时创建的)


在第二个示例中发生的情况是,
None
确实在定义中得到计算(它的计算结果为
None
duh!),但是有条件地将
[]
赋值给
L
的代码只会被编译,并且每次都会运行(条件通过)。

L=[]
在函数声明中,Python基本上是这样做的:

  • 此函数有一个名为
    L
  • 它的默认参数是
    []
    ,让我们把这个特殊的
    []
    放在一边,在没有为
    L
    传递参数时使用它
  • 每次调用函数时,创建一个变量
    L
    ,并为其分配传递的参数或我们先前设置的值

因此,
[]
部分将执行一次,这将创建一个列表对象,该对象被放在一边并保留在周围,这就是为什么如果您修改它,它会累积更改。同样的事情也发生在
None
上,但是
None
并没有被修改,也不能改变,所以你没有看到任何奇怪的副作用
None
仍然只被“执行”一次,而特定的
None
值也像列表一样被放在一边,只是你没有对
None
值本身做任何事情。

“为什么
L=None
不会每次都被调用”–我不知道你想说什么。我假设
L=None
每次都会被调用/执行。这就是为什么在第二个函数
fun2()
中,如果L为None,则条件
每次都为true。默认参数在函数声明中求值。空列表是可变的,所以在每个函数调用中都编辑相同的列表。附加到它不会创建新对象。如果没有,则在函数体中创建列表。每次从函数返回新列表时。但我正在将
fun2()中的
if
条件中的
L=None
更改为
L=[]
。为什么此赋值/更改不是永久性的或对其他后续函数调用不可见。再次说明:每次调用函数时,都会创建变量
L
,并为其赋值。值
[]
是永久的,而不是与
L
的关联。值
[]
存储您
的内容。将
附加到它,而不是
L
。内存中的永久对象
[]
与指向它的变量
L
不同。