Python append() 与列表上的 + 运算符,为啥这些会给出不同的结果?

Posted

技术标签:

【中文标题】Python append() 与列表上的 + 运算符,为啥这些会给出不同的结果?【英文标题】:Python append() vs. + operator on lists, why do these give different results?Python append() 与列表上的 + 运算符,为什么这些会给出不同的结果? 【发布时间】:2022-01-21 06:27:42 【问题描述】:

为什么这两个操作(append() resp. +)给出不同的结果?

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

【问题讨论】:

非常尊重一个可行的新问题:我回滚到原始问题以保持其干净(每个线程 1 个问题,请参阅 SO FAQ)。请在每个答案下方的评论线程中提出新问题或提出后续问题。 注意:您的编辑不会丢失,点击历史记录,您可以将其复制/粘贴到新问题中。 类似+=: ***.com/questions/725782/… 它似乎给出了不同的ans,但不是那样的。如果要使用 + 运算符添加值,则必须使用 [] 符号。 c += [c] 会给你与 append 相同的结果。 @SharifChowdhury 我相信你会得到同样的结果 【参考方案1】:

解释“为什么”:

+ operation 将array 元素添加到原始数组中。 array.append 操作将数组(或任何对象)插入到原始数组的末尾,这会导致在该位置对 self 的引用(因此是无限递归)。

这里的区别在于 + 操作在您通过连接元素添加数组(它像其他数组一样重载,请参阅序列上的this chapter)时执行特定操作。然而,附加方法确实按照您的要求执行:将对象附加到您给它的右侧(数组或任何其他对象),而不是获取它的元素。

另一种选择

如果您想使用类似于 + 运算符的函数,请使用 extend()(正如其他人在此处显示的那样)。反其道而行之是不明智的:尝试使用 + 运算符模拟列表的追加(请参阅我的 earlier link 了解原因)。

小历史

为了好玩,来点历史:1993 年 2 月的birth of the array module in Python。这可能会让您感到惊讶,但数组是在序列和列表出现之后添加的。

【讨论】:

+1 因为我总是支持准确的信息。官方文档的链接总是一个加号! “为什么”的另一部分:理智的人期望 + 是对称的:将列表与列表连接起来。 +1,Beni 好点(虽然我可以认为说“rh 侧的对象附加到 lh 侧的数组”只是“理智”,但个人发现当前的行为更明智)。 如果一个元素是单个字符串,例如s = '单词',l = ['this','is']。那么 l.append(s) 和 l+s 应该是一样的。我说的对吗? @juanpa.arrivillaga,等等,列表与数组。我明天会检查以更新我的答案,我现在明白了,tx!【参考方案2】:

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

“+”连接的替代方法

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

旁白

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

数组

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

来自array docs:

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

【讨论】:

【参考方案3】:

append 正在将一个元素附加到列表中。如果您想使用新列表扩展列表,您需要使用extend

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

【讨论】:

我以为很清楚为什么结果不一样,因为操作不一样!如果看起来+extend 产生不同的结果,我们会考虑一些事情。 +1:为什么我不喜欢“为什么”问题:append+ 是不同的。这就是为什么。我喜欢这个答案,因为提供的做法更有意义。 这个网站不是用来回答问题的吗?人们问为什么 php 被称为 PHP 以及为什么 __lt__ 不能在 Python 中被重载(现在它可以)。为什么问题是最重要的问题,但通常也是最难回答的问题:它们要求的是本质,而不是指向手册的指针。当然:如果你不喜欢一个问题(我最不喜欢),那就不要回答 ;-) 为了进一步的演示,也可以显示c += [c]c.append(c[:]) @Abel:为什么是a+b != a*b?它们是不同的操作。这就是答案。 “为什么”不如其他问题有用,例如“我怎样才能正确追加?”或者“这个导致无限递归的附加有什么问题?” “我对 X 做什么”或“我做 X 出了什么问题”形式的问题?或者“我应该做什么而不是 X”也可以帮助某人学习,但会提供有针对性、实用、可操作的答案。【参考方案4】:

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

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

所以这些实际上只是设计用来做不同事情的不同表达方式。

【讨论】:

【参考方案5】:

您要查找的方法是extend()。来自 Python documentation:

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).

【讨论】:

【参考方案6】:

你应该使用extend()

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

其他信息:append vs. extend

【讨论】:

【参考方案7】:

见the documentation:

list.append(x)

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

list.extend(L) - 通过附加给定列表中的所有项目来扩展列表; 相当于 a[len(a):] = L.

c.append(c)“附加”c 作为元素。由于列表是一种引用类型,这会创建一个递归数据结构。

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

【讨论】:

以上是关于Python append() 与列表上的 + 运算符,为啥这些会给出不同的结果?的主要内容,如果未能解决你的问题,请参考以下文章

Python串联与列表上的追加速度

python列表之append与extend方法比较

python list中append()与extend()用法

Python学习之路:列表(List)的append()extend()与insert()方法

Python列表合并去重和排序

python中append()与extend()方法的区别