将列表作为默认函数参数的奇怪行为

Ble*_*der 1 python list default-arguments

可能重复:
Python中的"最小惊讶":Mutable默认参数
列表扩展奇怪行为
使用方法名称进行金字塔遍历视图查找

假设我有这个功能:

def a(b=[]):
    b += [1]
    print b
Run Code Online (Sandbox Code Playgroud)

调用它会产生以下结果:

>>> a()
[1]
>>> a()
[1, 1]
>>> a()
[1, 1, 1]
Run Code Online (Sandbox Code Playgroud)

当我改为b += [1]b = b + [1],函数的行为会改变:

>>> a()
[1]
>>> a()
[1]
>>> a()
[1]
Run Code Online (Sandbox Code Playgroud)

b = b + [1]什么不同b += [1]?为什么会这样?

Jon*_*nts 5

b += [1]改变功能默认值(导致最不惊讶的FAQ).b = b + [1]采用默认参数b- 使用,创建一个新列表+ [1],并将其绑定到b.一个变异列表 - 另一个创建一个新列表.


Bre*_*arn 5

在Python中,不能保证a += b做同样的事情a = a + b.

对于列表,在适当位置someList += otherList修改someList,基本等效于someList.extend(otherList),然后将名称重新绑定someList到同一列表. someList = someList + otherList另一方面,通过连接两个列表构造一个列表,并将名称绑定someList到该新列表.

这意味着+=,当名称最终指向它已经指向的同一个对象时+,它会指向一个新对象.由于函数默认值仅被评估一次(参见这个被引用很多的问题),这意味着+=操作堆积起来因为它们都修改了相同的原始对象(默认参数).