Python 的列表方法 append 和 extend 有什么区别?

问:

这个问题的答案是社区的努力。编辑现有答案以改进这篇文章。它目前不接受新的答案或交互。

列表方法 append() 和 extend() 有什么区别?

答1:

huntsbot.com提供全网独家一站式外包任务、远程工作、创意产品分享与订阅服务!

append 在列表末尾附加一个指定对象:

>>> x = [1, 2, 3]
>>> x.append([4, 5])
>>> print(x)
[1, 2, 3, [4, 5]]

extend 通过附加来自指定迭代的元素来扩展列表:

>>> x = [1, 2, 3]
>>> x.extend([4, 5])
>>> print(x)
[1, 2, 3, 4, 5]

extend 和仅使用加法运算符(在上面的示例中为 x = x + [4, 5])有什么区别?

实际上有一个很大的不同 - x + [4, 5] 为您提供了一个分配给 x 的新列表 - x.extend() 改变了原始列表。我在下面的答案中详细说明。

@AaronHall @Rohan 但它与 x += [4,5] 相同。

使用 append 时的关键字是 Object。如果您尝试使用 extend 并传入 dictionary,它会将 key 而不是整个哈希附加到数组的末尾。

@Rohan, x = x + [4, 5] 的时间复杂度为 O(len(x) + len([4,5])) 其中 extend 的时间复杂度为 O(len([4, 5 ]))

答2:

huntsbot.com洞察每一个产品背后的需求与收益,从而捕获灵感

append 将元素添加到列表中。 extend 将第一个列表与另一个列表/可迭代连接。

>>> xs = ['A', 'B']
>>> xs
['A', 'B']

>>> xs.append("D")
>>> xs
['A', 'B', 'D']

>>> xs.append(["E", "F"])
>>> xs
['A', 'B', 'D', ['E', 'F']]

>>> xs.insert(2, "C")
>>> xs
['A', 'B', 'C', 'D', ['E', 'F']]

>>> xs.extend(["G", "H"])
>>> xs
['A', 'B', 'C', 'D', ['E', 'F'], 'G', 'H']

答3:

huntsbot.com洞察每一个产品背后的需求与收益,从而捕获灵感

列表方法追加和扩展有什么区别?

append 将其参数作为单个元素添加到列表的末尾。列表本身的长度将增加一。

extend 迭代其参数,将每个元素添加到列表中,扩展列表。无论可迭代参数中有多少元素,列表的长度都会增加。

附加

list.append 方法将一个对象附加到列表的末尾。

my_list.append(object) 

无论对象是什么,无论是数字、字符串、另一个列表还是其他对象,它都会作为列表中的单个条目添加到 my_list 的末尾。

>>> my_list
['foo', 'bar']
>>> my_list.append('baz')
>>> my_list
['foo', 'bar', 'baz']

所以请记住,列表是一个对象。如果您将另一个列表附加到列表中,则第一个列表将是列表末尾的单个对象(这可能不是您想要的):

>>> another_list = [1, 2, 3]
>>> my_list.append(another_list)
>>> my_list
['foo', 'bar', 'baz', [1, 2, 3]]
                     #^^^^^^^^^--- single item at the end of the list.

延长

list.extend 方法通过附加来自可迭代对象的元素来扩展列表:

my_list.extend(iterable)

因此,通过扩展,可迭代的每个元素都被附加到列表中。例如:

>>> my_list
['foo', 'bar']
>>> another_list = [1, 2, 3]
>>> my_list.extend(another_list)
>>> my_list
['foo', 'bar', 1, 2, 3]

请记住,字符串是可迭代的,因此如果您使用字符串扩展列表,您将在迭代字符串时附加每个字符(这可能不是您想要的):

>>> my_list.extend('baz')
>>> my_list
['foo', 'bar', 1, 2, 3, 'b', 'a', 'z']

运算符重载,add (+) 和 iadd (+=)

  • 和 += 运算符都是为 list 定义的。它们在语义上类似于扩展。

my_list + another_list 在内存中创建第三个列表,因此您可以返回它的结果,但它要求第二个可迭代对象是一个列表。

my_list += another_list 就地修改列表(它是就地运算符,并且列表是可变对象,正如我们所见),因此它不会创建新列表。它也像extend一样工作,因为第二个iterable可以是任何类型的iterable。

不要混淆 - my_list = my_list + another_list 不等同于 += - 它为您提供分配给 my_list 的全新列表。

时间复杂度

追加有 (amortized) constant time complexity, O(1)。

Extend 具有时间复杂度 O(k)。

遍历对 append 的多次调用会增加复杂性,使其与 extend 等效,并且由于 extend 的迭代是在 C 中实现的,因此如果您打算将可迭代的连续项附加到列表中,它总是会更快。

关于“摊销”——来自 list object implementation source:

    /* This over-allocates proportional to the list size, making room
     * for additional growth.  The over-allocation is mild, but is
     * enough to give linear-time amortized behavior over a long
     * sequence of appends() in the presence of a poorly-performing
     * system realloc().

这意味着我们预先获得了大于需要的内存重新分配的好处,但我们可能会在下一次边际重新分配时付出更大的代价。所有追加的总时间在 O(n) 处是线性的,并且每个追加分配的时间变为 O(1)。

表现

您可能想知道什么更高效,因为 append 可用于实现与 extend 相同的结果。以下函数做同样的事情:

def append(alist, iterable):
    for item in iterable:
        alist.append(item)
        
def extend(alist, iterable):
    alist.extend(iterable)

所以让我们给他们计时:

import timeit

>>> min(timeit.repeat(lambda: append([], "abcdefghijklmnopqrstuvwxyz")))
2.867846965789795
>>> min(timeit.repeat(lambda: extend([], "abcdefghijklmnopqrstuvwxyz")))
0.8060121536254883

解决对时间的评论

一位评论者说:

完美的答案,我只是错过了比较只添加一个元素的时间

做语义上正确的事情。如果您想在一个可迭代对象中追加所有元素,请使用 extend。如果您只是添加一个元素,请使用 append。

好的,让我们创建一个实验,看看它是如何及时完成的:

def append_one(a_list, element):
    a_list.append(element)

def extend_one(a_list, element):
    """creating a new list is semantically the most direct
    way to create an iterable to give to extend"""
    a_list.extend([element])

import timeit

而且我们看到,为了使用扩展而特意创建一个可迭代的对象是(轻微的)时间浪费:

>>> min(timeit.repeat(lambda: append_one([], 0)))
0.2082819009956438
>>> min(timeit.repeat(lambda: extend_one([], 0)))
0.2397019260097295

我们从中了解到,当我们只有 一个 元素要附加时,使用 extend 没有任何好处。

此外,这些时间并不那么重要。我只是向他们表明,在 Python 中,做语义正确的事情就是用正确的方式做事™。

可以想象,您可能会在两个可比较的操作上测试时序并得到模棱两可或相反的结果。只专注于做语义上正确的事情。

结论

我们看到 extend 在语义上更清晰,并且它可以比 append 运行得更快,当您打算将迭代中的每个元素附加到列表时。

如果您只有一个元素(不在迭代中)要添加到列表中,请使用 append。

@Aaron Hall 关于计时算法的一个小评论。 “extend_one”可能会返回“稍微错误”的时间,因为还涉及到列表的创建。如果您想更加严格,最好将项目创建为变量(ex1 = 0 和 ex2 = [0])并传递这些变量。

确实是完美的答案。 l1 += l2 与 l1.extend(l2) 的性能如何?

@Jean-FrancoisT.:l1 += l2 和 l1.extend(l2) 最终执行相同的代码(listobject.c 中的 list_extend 函数)。唯一的区别是: 1. += 重新分配 l1(对于 list s,但重新分配支持不可变类型,之后不是同一个对象),如果 l1 实际上是不可变对象的属性;例如,t = ([],)、t[0] += lst 会失败,而 t[0].extend(lst) 会起作用。 2. l1 += l2 使用专用字节码,而 l1.extend(l2) 使用通用方法调度;这使得 += 比 extend 快。

+= 必须重新分配 l1 的事实确实意味着在某些情况下,extend 的较慢调度部分或全部通过不分配回左侧来弥补。例如,如果 list 是一个对象的属性,则 self.l1 += l2 和 self.l1.extend(l2) 在我的 Python 3.6 安装上具有相同的性能,仅仅是因为实际操作更像 self.l1 = self.l1.__iadd__(l2),这意味着它必须执行适度昂贵的STORE_ATTR 而 self.l1.extend(l2) 则不必。

本地测试中的简单比较:对于一个本地变量(因此 += 只是使用 STORE_FAST,它非常便宜),其中要添加的值是一个现有的 list,其中包含一个项目,重复操作1000 次,+= 平均耗时约 33 ns,而 extend 耗时 78 ns,相差 45 ns。如果 l1 是全局的(需要更昂贵的 STORE_GLOBAL),则差异缩小到 17 ns。如果 l1 实际上是 local.l1(需要更昂贵的 STORE_ATTR),则 += 和 extend 之间没有有意义的区别(时间大致相同;extend 有时会胜出)。

答4:

HuntsBot周刊–不定时分享成功产品案例,学习他们如何成功建立自己的副业–huntsbot.com

append 附加一个元素。 extend 附加元素列表。

请注意,如果您传递一个列表来追加,它仍然会添加一个元素:

>>> a = [1, 2, 3]
>>> a.append([4, 5, 6])
>>> a
[1, 2, 3, [4, 5, 6]]

huntsbot.com高效搞钱,一站式跟进超10+任务平台外包需求

答5:

huntsbot.com高效搞钱,一站式跟进超10+任务平台外包需求

追加与扩展

使用 append,您可以附加一个将扩展列表的元素:

>>> a = [1,2]
>>> a.append(3)
>>> a
[1,2,3]

如果你想扩展多个元素,你应该使用extend,因为你只能附加一个元素或一个元素列表:

>>> a.append([4,5])
>>> a
>>> [1,2,3,[4,5]]

这样你就得到一个嵌套列表

而不是使用extend,您可以像这样扩展单个元素

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

或者,与追加不同,一次扩展更多元素而不将列表嵌套到原始列表中(这就是名称扩展的原因)

>>> a.extend([4,5,6])
>>> a
[1,2,3,4,5,6]

使用两种方法添加一个元素

append 和 extend 都可以将一个元素添加到列表的末尾,尽管 append 更简单。

追加 1 个元素

>>> x = [1,2]
>>> x.append(3)
>>> x
[1,2,3]

扩展一个元素

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

添加更多元素…具有不同的结果

如果您对多个元素使用 append,则必须将元素列表作为参数传递,您将获得一个 NESTED 列表!

>>> x = [1,2]
>>> x.append([3,4])
>>> x
[1,2,[3,4]]

相反,使用extend,您将一个列表作为参数传递,但您将获得一个包含未嵌套在旧元素中的新元素的列表。

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

因此,对于更多元素,您将使用 extend 来获取包含更多项目的列表。但是,追加列表不会向列表中添加更多元素,而是添加一个嵌套列表的元素,您可以在代码输出中清楚地看到。

https://i.stack.imgur.com/lJK1M.png

https://i.stack.imgur.com/KC2Ji.png

答6:

huntsbot.com洞察每一个产品背后的需求与收益,从而捕获灵感

以下两个片段在语义上是等效的:

for item in iterator:
    a_list.append(item)

a_list.extend(iterator)

后者可能会更快,因为循环是用 C 实现的。

在我的机器上扩展比在循环中附加快约 4 倍(16us 对 4us 用于 100 个零循环)

extend() 可能预分配,而 append() 可能没有。

@MadPhysicist:为了完整起见,有时 extend() 无法 明智地预先分配,因为某些迭代没有实现 __len__(),但像你一样,如果它没有实现,我会感到惊讶不要尝试。正如 Aaron's answer 中所指出的,一些性能提升还来自于在纯 C 中而不是在 Python 中执行迭代部分。

答7:

与HuntsBot一起,探索全球自由职业机会–huntsbot.com

append() 方法将单个项目添加到列表的末尾。

x = [1, 2, 3]
x.append([4, 5])
x.append('abc')
print(x)
# gives you
[1, 2, 3, [4, 5], 'abc']

extend() 方法采用一个参数,一个列表,并将参数的每个项目附加到原始列表。 (列表被实现为类。“创建”列表实际上是实例化一个类。因此,列表具有对其进行操作的方法。)

x = [1, 2, 3]
x.extend([4, 5])
x.extend('abc')
print(x)
# gives you
[1, 2, 3, 4, 5, 'a', 'b', 'c']

来自 Dive Into Python。

您不能仅使用 6 进行扩展,因为它不可迭代。您示例中的第二个输出是错误的。 'abc' 被添加为单个元素,因为您将它作为具有一个元素 ['abc'] 的列表传递给 extend:[1, 2, 3, 4, 5, 'abc']。要使示例输出正确,请将 abc 行更改为:x.extend('abc')。并删除 x.extend(6) 或将其更改为 x.extend([6])。

“extend() 方法接受一个参数,一个列表”也是错误的

答8:

huntsbot.com聚合了超过10+全球外包任务平台的外包需求,寻找外包任务与机会变的简单与高效。

您可以使用“+”返回扩展,而不是就地扩展。

l1=range(10)

l1+[11]

[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 11]

l2=range(10,1,-1)

l1+l2

[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 9, 8, 7, 6, 5, 4, 3, 2]

与 += 类似,用于就地行为,但与 append & 略有不同extend。 += 与 append 和 extend 的最大区别之一是它用于函数范围时,请参阅 this blog post。

使用“+”返回扩展对时间复杂度有影响吗?

@franklin,有关详细信息,请参阅此答案:stackoverflow.com/a/28119966/2230844

我不明白这是如何回答问题的

答9:

一个优秀的自由职业者,应该有对需求敏感和精准需求捕获的能力,而huntsbot.com提供了这个机会

append(object) - 通过将对象添加到列表来更新列表。

x = [20]
# List passed to the append(object) method is treated as a single object.
x.append([21, 22, 23])
# Hence the resultant list length will be 2
print(x)
--> [20, [21, 22, 23]]

extend(list) - 本质上连接两个列表。

x = [20]
# The parameter passed to extend(list) method is treated as a list.
# Eventually it is two lists being concatenated.
x.extend([21, 22, 23])
# Here the resultant list's length is 4
print(x)
[20, 21, 22, 23]

答10:

huntsbot.com洞察每一个产品背后的需求与收益,从而捕获灵感

这相当于使用 + 运算符的 append 和 extend:

>>> x = [1,2,3]
>>> x
[1, 2, 3]
>>> x = x + [4,5,6] # Extend
>>> x
[1, 2, 3, 4, 5, 6]
>>> x = x + [[7,8]] # Append
>>> x
[1, 2, 3, 4, 5, 6, [7, 8]]

答11:

huntsbot.com高效搞钱,一站式跟进超10+任务平台外包需求

extend() 可以与迭代器参数一起使用。这是一个例子。您希望以这种方式从列表列表中创建一个列表:

list2d = [[1,2,3],[4,5,6], [7], [8,9]]

你要

>>>
[1, 2, 3, 4, 5, 6, 7, 8, 9]

您可以使用 itertools.chain.from_iterable() 来执行此操作。该方法的输出是一个迭代器。它的实现等价于

def from_iterable(iterables):
    # chain.from_iterable(['ABC', 'DEF']) --> A B C D E F
    for it in iterables:
        for element in it:
            yield element

回到我们的例子,我们可以做

import itertools
list2d = [[1,2,3],[4,5,6], [7], [8,9]]
merged = list(itertools.chain.from_iterable(list2d))

并获得通缉名单。

下面是如何等效地将 extend() 与迭代器参数一起使用:

merged = []
merged.extend(itertools.chain.from_iterable(list2d))
print(merged)
>>>
[1, 2, 3, 4, 5, 6, 7, 8, 9]

huntsbot.com高效搞钱,一站式跟进超10+任务平台外包需求

原文链接:https://www.huntsbot.com/qa/rDR0/what-is-the-difference-between-pythons-list-methods-append-and-extend?lang=zh_CN&from=csdn

huntsbot.com – 高效赚钱,自由工作

  • 2
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值