Python 在列表中追加()与 + 操作符,为什么这些给出不同的结果?

为什么这两种操作(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是一样的。为什么与 +操作不同?

156712 次浏览

解释“为什么”:

+操作数组元素添加到原始数组中。array.append操作将数组(或任何对象)插入到原始数组的末尾,这将在该点处产生一个 提到自己(因此在使用列表的情况下是无限递归的,尽管对于数组,您将收到一个类型错误)。

这里的不同之处在于,当您通过连接元素添加一个数组时,+操作的作用是特定的(与其他操作一样,它也是重载的,请参阅序列 这一章)。然而,append-方法完全按照您的要求执行: 将对象附加到您给它的右侧(数组或任何其他对象) ,而不是获取它的元素。

另一个选择

如果希望使用与 +操作符类似的函数,请使用 extend()(正如其他函数所示)。与之相反的做法是不明智的: 尝试用列表的 +操作符模仿 append(请参阅我的 更早的链接中的原因)。更多关于下列清单的资料:

清单

一些评论者认为这个问题是关于列表的,而不是关于数组的。问题变了,虽然我应该早点把这个包括进去。

以上关于 array的大部分内容也适用于清单:

  • +操作符将两个列表连接在一起。操作符将返回一个新的列表对象。
  • List.append不是一个列表与另一个列表的 附录,而是在当前列表末尾的 附加一个对象(这里是 list)。因此,将 c添加到它本身会导致无限递归。
  • 与使用数组一样,可以使用 List.extend添加带有另一个列表(或 iterable)的扩展列表。这将更改当前列表 原地待命,而不是返回新列表的 +

小历史

有趣的是,一点历史: 1993年2月的 Python 中数组模块的诞生。这可能会让你感到惊讶,但是数组是在序列和列表出现之后才加入的。

append正在向列表追加一个元素。如果要使用新列表扩展列表,则需要使用 extend

>>> c = [1, 2, 3]
>>> c.extend(c)
>>> c
[1, 2, 3, 1, 2, 3]

Python 列表是异构的,即同一列表中的元素可以是任何类型的对象。表达式: c.append(c)将对象 c追加到列表中。在这种情况下,它使列表本身成为列表的一个成员。

表达式 c += c将两个列表相加,并将结果赋给变量 c。在列表上定义重载的 +操作符,以创建一个新列表,其内容是第一个列表中的元素和第二个列表中的元素。

所以这些只是用来设计不同事物的不同表达方式。

你应该使用扩展()

>>> c=[1,2,3]
>>> c.extend(c)
>>> c
[1, 2, 3, 1, 2, 3]

其他信息: 附加与扩展

您正在寻找的方法是 extend():

list.append(x)
Add an item to the end of the list; equivalent to a[len(a):] = [x].


list.extend(L)
Extend the list by appending all the items in the given list; equivalent to a[len(a):] = L.


list.insert(i, x)
Insert an item at a given position. The first argument is the index of the element before which to insert, so a.insert(0, x) inserts at the front of the list, and a.insert(len(a), x) is equivalent to a.append(x).

文件:

Append (x)

  • 在列表的末尾添加一个项; 相当于[ len (a) : ] = [ x ]。

扩展(L) - 扩大清单的范围,附加给定清单中的所有项目; 相当于[ len (a) : ] = L。

由于列表是一个引用类型,这就创建了一个递归的数据结构。

c += c等价于将 C 的元素附加到 c 的 extend(c)

连接操作符 +是一个二进制中缀操作符,当应用于列表时,它返回一个新列表,其中包含两个操作数中每个操作数的所有元素。list.append()方法是 list.append()0上的 mutator,它将其单个 object参数(在您的特定示例中是列表 c)附加到主体 list.append()0。在您的示例中,这会导致 c将引用附加到自身(因此是无限递归)。

’+’连接的替代方法

list.extend()方法也是一个 mutator 方法,它将其 sequence参数与主题 list连接起来。具体来说,它按照迭代顺序附加 sequence的每个元素。

旁白

作为操作符,+将表达式的结果作为新值返回。作为一个非链式 mutator方法,list.extend()就地修改主题列表并且不返回任何内容。

阵列

我之所以添加这个,是因为上面 Abel 的回答混合了列表、序列和数组的讨论可能会引起潜在的混淆。 在序列和列表之后,Arrays 被添加到 Python 中,作为存储整数数据类型的数组的一种更有效的方法。不要混淆 arrayslists。他们不一样。

来自 数组文档:

数组是序列类型,其行为与列表非常相似,只是其中存储的对象类型受到约束。类型是在对象创建时使用类型代码指定的,类型代码是单个字符。