Python 的 append() 和 + 运算符在列表中为什么结果不同?
这两个操作(append()
和+
)为什么会得到不同的结果呢?
>>> c = [1, 2, 3]
>>> c
[1, 2, 3]
>>> c += c
>>> c
[1, 2, 3, 1, 2, 3]
>>> c = [1, 2, 3]
>>> c.append(c)
>>> c
[1, 2, 3, [...]]
>>>
在最后一种情况下,实际上是出现了无限递归。c[-1]
和c
是一样的。那为什么用+
操作时就不一样呢?
7 个回答
append
是把一个元素添加到列表里。如果你想用一个新列表来扩展原来的列表,就需要使用 extend
。
>>> c = [1, 2, 3]
>>> c.extend(c)
>>> c
[1, 2, 3, 1, 2, 3]
连接运算符 +
是一个二元运算符,当它用于列表时,会返回一个新列表,这个新列表包含了两个操作数的所有元素。list.append()
方法是一个修改器,它会把你传入的单个对象(在你的例子中是列表 c
)添加到目标列表中。在你的例子里,这就导致了 c
自己添加了一个引用(所以出现了无限递归)。
使用 '+' 连接的替代方法
list.extend()
方法也是一个修改器,它会把你传入的序列与目标列表连接起来。具体来说,它会按顺序将序列中的每个元素添加到目标列表中。
补充说明
作为一个运算符,+
会返回一个新值。而作为一个非链式的 mutator
方法,list.extend()
会直接修改目标列表,并且不返回任何值。
数组
我加上这一部分是因为上面的 Abel 的回答可能会让人对列表、序列和数组混淆。 数组
是在 Python 中引入的,目的是为了更高效地存储整型数据类型的数组。不要把 arrays
和 lists
混淆,它们是不同的。
来自 数组文档:
数组是序列类型,行为与列表非常相似,但存储的对象类型是有限制的。这个类型是在创建对象时通过一个类型代码指定的,类型代码是一个单字符。
解释一下“为什么”:
在Python中,+
操作是用来把一个数组的元素加到另一个数组里的。而array.append
操作则是把一个数组(或者其他任何对象)放到原数组的最后面,这样在那个位置就会出现一个自我引用(这就是你在处理列表时出现无限递归的原因,不过在数组中,你会遇到类型错误)。
这里的区别在于,+
操作在你加一个数组时是有特定功能的(它像其他操作一样被重载,具体可以看这一章关于序列的内容),它是把元素连接在一起。而append
方法则是字面意思地执行你要求的操作:把你给它的右边的对象(数组或其他对象)放到当前数组的最后,而不是取它的元素。
一个替代方案
如果你想用一个和+
操作类似的功能,可以使用extend()
。这样做比用+
操作来模拟append
更明智(其他人也在这里提到过)。下面会详细讲讲列表:
列表
[编辑] 有几位评论者提到这个问题是关于列表而不是数组。问题的确发生了变化,不过我应该早一点提到这一点。
上面关于array
的内容大部分也适用于列表:
+
操作符是用来把两个列表连接在一起的。这个操作会返回一个新的列表对象。List.append
并不是把一个列表加到另一个列表上,而是把一个单独的对象(这里是一个list
)放到你当前列表的最后。因此,把c
加到自己上,就会导致无限递归。- 和数组一样,你可以使用
List.extend
来把一个列表扩展到另一个列表(或者其他可迭代对象)。这样会直接改变你当前的列表,而不是像+
那样返回一个新列表。
一点历史
有趣的是,简单说说历史:Python中的数组模块诞生于1993年2月。可能会让你惊讶的是,数组是在序列和列表出现很久之后才被添加进来的。