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

What is the difference between Python's list methods append and extend?

提问人:Claudiu 提问时间:10/31/2008 最后编辑:dreftymacClaudiu 更新时间:4/21/2023 访问量:3261015

问:

这个问题的答案是社区的努力。编辑现有答案以改进此帖子。它目前不接受新的答案或互动。

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

python list data-structures append extend

评论


答:

137赞 Greg Hewgill 10/31/2008 #1

append追加单个元素。 追加元素列表。extend

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

>>> a = [1, 2, 3]
>>> a.append([4, 5, 6])
>>> a
[1, 2, 3, [4, 5, 6]]
737赞 Harley Holcombe 10/31/2008 #2

.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']
5855赞 kender 10/31/2008 #3

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

评论

171赞 Rohan 5/30/2017
在上面的例子中,和简单地使用加法运算符有什么区别?extendx = x + [4, 5]
410赞 Russia Must Remove Putin 7/18/2017
实际上有一个很大的区别 - 给你一个分配给 x 的新列表 - 改变原来的列表。我在下面的回答中详细说明。x + [4, 5]x.extend()
10赞 Astitva Srivastava 12/13/2018
@AaronHall @Rohan但与 .x += [4,5]
2赞 Anthony 3/15/2019
使用时的关键字是 Object。如果您尝试使用并传入字典,它将附加,而不是将整个哈希值附加到数组的末尾。appendextend
2赞 mcagriardic 7/23/2020
@Rohan,x = x + [4, 5] 的时间复杂度为 O(len(x) + len([4,5])),其中 as extend 具有 O(len([4, 5])) 的时间复杂度
67赞 Nova 8/21/2012 #4

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

for item in iterator:
    a_list.append(item)

a_list.extend(iterator)

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

评论

22赞 Alex L 12/27/2012
在我的机器上,扩展比在循环中追加快 ~4 倍(16 个零循环为 4 个 100 个 us)
6赞 Mad Physicist 10/23/2015
extend()可能是预分配的,而很可能没有。append()
0赞 Soren Bjornstad 7/28/2019
@MadPhysicist:为了完整性起见,有时无法合理地预分配,因为某些可迭代对象没有实现,但像你一样,如果它不尝试,我会感到惊讶。正如 Aaron 的回答所指出的那样,一些性能提升也来自于用纯 C 而不是 Python 进行迭代部分。extend()__len__()
23赞 kiriloff 5/13/2013 #5

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]
25赞 Chaitanya 5/13/2013 #6

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]
41赞 denfromufa 8/26/2013 #7

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

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]

与就地行为类似,但与 & 略有不同。from 和 的最大区别之一是它在函数作用域中使用时,请参阅这篇博文+=appendextend+=appendextend

评论

0赞 franklin 7/19/2015
使用“+”返回扩展对时间复杂度有影响吗?
5赞 denfromufa 7/21/2015
@franklin,有关详细信息,请参阅此答案:stackoverflow.com/a/28119966/2230844
3赞 pppery 7/13/2018
我不明白这如何回答这个问题
0赞 blackraven 8/26/2022
我认为比list.extend([item])list.append(item)
47赞 CodyChan 10/31/2013 #8

该方法将单个项添加到列表的末尾。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']

深入了解 Python

评论

0赞 aneroid 9/25/2014
你不能只用 6 来扩展,因为它是不可迭代的。您示例中的第二个输出是错误的。'abc' 被添加为单个元素,因为你把它作为一个带有一个元素的列表传递到:[1, 2, 3, 4, 5, 'abc']。要使示例输出正确,请将 abc 行更改为:。并删除或将其更改为 .extend['abc']x.extend('abc')x.extend(6)x.extend([6])
0赞 am70 2/4/2022
此外,“extend() 方法接受一个参数,一个列表”是错误的
23赞 skdev75 7/8/2014 #9

这相当于使用运算符:appendextend+

>>> 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]]
15赞 bconstanzo 8/6/2014 #10

一个已经暗示但未解释的有趣观点是,扩展比追加更快。对于任何带有 append inside 的循环,都应被视为替换为 list.extend(processed_elements)。

请记住,附加新元素可能会导致整个列表重新定位到内存中的更好位置。如果我们一次附加 1 个元素而多次执行此操作,则整体性能会受到影响。从这个意义上说,list.extend 类似于 “”.join(stringlist)。

15赞 Shiv 10/16/2014 #11

Append 会立即添加整个数据。整个数据将被添加到新创建的索引中。另一方面,顾名思义,它扩展了当前数组。extend

例如

list1 = [123, 456, 678]
list2 = [111, 222]

我们得到:append

result = [123, 456, 678, [111, 222]]

同时,我们得到:extend

result = [123, 456, 678, 111, 222]
657赞 Russia Must Remove Putin 1/24/2015 #12

list 方法 append 和 extend 有什么区别?

  • .append()将其参数作为单个元素添加到列表的末尾。列表本身的长度将增加 1。
  • .extend()循环访问其参数,将每个元素添加到列表中,从而扩展列表。无论可迭代参数中有多少元素,列表的长度都会增加。

.append()

该方法将一个对象追加到列表的末尾。.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.

.extend()

该方法通过从可迭代对象中追加元素来扩展列表:.extend()

my_list.extend(iterable)

因此,使用 extend,可迭代对象的每个元素都会被附加到列表中。例如:

>>> 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__ (+=)

和 运算符都定义为 。它们在语义上类似于 extend。++=list

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

my_list += another_list就地修改列表(它是就地运算符,正如我们所看到的,列表是可变对象),因此它不会创建新列表。它的工作方式也类似于扩展,因为第二个可迭代对象可以是任何类型的可迭代对象。

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

时间复杂度

追加具有(摊销的)常数时间复杂度 O(1)。

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

遍历多个调用以增加复杂性,使其等同于 extend,并且由于 extend 的迭代是在 C 语言中实现的,因此如果您打算将可迭代对象中的连续项追加到列表中,它总是会更快。.append()

关于“摊销” - 来自列表对象实现源

    /* 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

我们看到,不遗余力地创建一个可迭代的 extend 只是为了使用 extend 是一种(轻微的)时间浪费:

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

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

此外,这些时间并不那么重要。我只是向他们展示这一点,在 Python 中,做语义上正确的事情就是以正确的方式™做事。

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

结论

我们看到这在语义上更清晰,并且当您打算将可迭代对象中的每个元素附加到列表时,它的运行速度要快得多。.extend().append()

如果只有单个元素(不在可迭代对象中)要添加到列表中,请使用 。.append()

评论

1赞 ilias iliadis 4/1/2018
@Aaron Hall 时序算法中的一个小评论。“extend_one”可能会返回“略有错误”的时间,因为还涉及列表的创建。如果您想更严格,最好将项目创建为变量 ( 和 ) 并传递这些变量。ex1 = 0ex2 = [0]
22赞 Jean-Francois T. 4/23/2018
确实是完美的答案。vs 的性能如何?l1 += l2l1.extend(l2)
12赞 ShadowRanger 8/18/2018
@Jean-FrancoisT.:并最终执行相同的代码(中的函数)。唯一的区别是:1.重新赋值(对于 s 来说,重赋本身,但重赋支持之后不是同一对象的不可变类型),如果实际上是不可变对象的属性,则它是非法的;例如,将失败,而将起作用。2.使用专用字节码,同时使用广义方法调度;这使得比 .l1 += l2l1.extend(l2)list_extendlistobject.c+=l1listl1t = ([],)t[0] += lstt[0].extend(lst)l1 += l2l1.extend(l2)+=extend
4赞 ShadowRanger 8/18/2018
必须重新分配的事实确实意味着在某些情况下,通过不分配回左侧来部分或全部弥补较慢的调度。例如,如果 是对象的一个属性,并且在我的 Python 3.6 安装中具有相同的性能,仅仅是因为实际操作更像是 ,这意味着它必须执行一个中等成本的操作,而不必这样做。+=l1extendlistself.l1 += l2self.l1.extend(l2)self.l1 = self.l1.__iadd__(l2)STORE_ATTRself.l1.extend(l2)
3赞 ShadowRanger 8/18/2018
局部测试中的简单比较:对于一个局部变量(所以只是使用 ,这是超级便宜的),其中添加的值是一个包含一个项目的现有值,重复操作 1000 次,平均需要大约 33 ns,而需要 78 ns,相差 45 ns。如果是全局(需要更昂贵的),则差异缩小到 17 ns。如果 实际上 (需要更昂贵 ), 和 之间没有有意义的区别 (时间大致相同; 有时赢)。+=STORE_FASTlist+=extendl1STORE_GLOBALl1local.l1STORE_ATTR+=extendextend
18赞 The Gr8 Adakron 6/13/2016 #13

append():在 Python 中基本上用于添加一个元素。

示例 1:

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

示例 2:

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

extend():其中 extend() 用于合并两个列表或在一个列表中插入多个元素。

示例 1:

>> a = [1, 2, 3, 4]
>> b = [5, 6, 7, 8]
>> a.extend(b)
>> print(a)
>> a = [1, 2, 3, 4, 5, 6, 7, 8]

示例 2:

>> a = [1, 2, 3, 4]
>> a.extend([5, 6])
>> print(a)
>> a = [1, 2, 3, 4, 5, 6]
3赞 tessie 9/1/2016 #14

extend(L)通过附加给定列表中的所有项目来扩展列表。L

>>> a
[1, 2, 3]
a.extend([4])  #is eqivalent of a[len(a):] = [4]
>>> a
[1, 2, 3, 4]
a = [1, 2, 3]
>>> a
[1, 2, 3]
>>> a[len(a):] = [4]
>>> a
[1, 2, 3, 4]
7赞 Crabime 2/11/2017 #15

我希望我能对这个问题做一个有益的补充。例如,如果您的列表存储了特定类型的对象,则存在该方法不适合的情况:在循环中,并且每次生成一个对象并将其存储到列表中,它将失败。例外情况如下:InfoextendforInfoextend

TypeError:“Info”对象不可迭代

但是,如果使用该方法,则结果是可以的。因为每次使用该方法时,它都会始终将其视为列表或任何其他集合类型,对其进行迭代,并将其放在上一个列表之后。显然,特定对象不能被迭代。appendextend

93赞 PythonProgrammi 10/18/2017 #16

追加与扩展

enter image description here

使用 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]

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

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

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

enter image description here

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 来获取包含更多项的列表。 但是,追加列表不会向列表中添加更多元素,而是向嵌套列表添加一个元素,正如您在代码输出中可以清楚地看到的那样。

enter image description here

enter image description here

5赞 Wizard 12/4/2017 #17

直观地区分它们

l1 = ['a', 'b', 'c']
l2 = ['d', 'e', 'f']
l1.append(l2)
l1
['a', 'b', 'c', ['d', 'e', 'f']]

这就像在她的身体里复制一个身体(嵌套)。l1

# Reset l1 = ['a', 'b', 'c']
l1.extend(l2)
l1
['a', 'b', 'c', 'd', 'e', 'f']

这就像两个分居的人结婚并建立了一个团结的家庭。

此外,我制作了所有列表方法的详尽备忘单供您参考。

list_methods = {'Add': {'extend', 'append', 'insert'},
                'Remove': {'pop', 'remove', 'clear'}
                'Sort': {'reverse', 'sort'},
                'Search': {'count', 'index'},
                'Copy': {'copy'},
                }
11赞 kmario23 12/31/2017 #18

英语词典将单词 和 定义为:appendextend

追加:在书面文档的末尾添加(内容)。
扩展:放大。放大或展开


有了这些知识,现在让我们了解一下

1)appendextend的区别

附加

  • 原样将任何 Python 对象追加到列表的末尾(即作为 列表中的最后一个元素)。
  • 生成的列表可以是嵌套的,并包含异构元素(即列表、字符串、元组、字典、集合等)。

扩展

  • 接受任何可迭代对象作为其参数,并使列表更大
  • 结果列表始终是一维列表(即没有嵌套),并且由于应用 .list(iterable)

2) appendextend 之间的相似性

  • 两者都只接受一个论点。
  • 两者都会就地修改列表。
  • 结果,两者都返回 .None

Example

lis = [1, 2, 3]

# 'extend' is equivalent to this
lis = lis + list(iterable)

# 'append' simply appends its argument as the last element to the list
# as long as the argument is a valid Python object
list.append(object)
0赞 ilias iliadis 4/1/2018 #19

append "extends" the list (in place) by only one item, the single object passed (as argument).

extend "extends" the list (in place) by as many items as the object passed (as argument) contains.

This may be slightly confusing for objects.str

  1. If you pass a string as argument: will add a single string item at the end but will add as many "single" 'str' items as the length of that string.appendextend
  2. If you pass a list of strings as argument: will still add a single 'list' item at the end and will add as many 'list' items as the length of the passed list.appendextend
def append_o(a_list, element):
    a_list.append(element)
    print('append:', end = ' ')
    for item in a_list:
        print(item, end = ',')
    print()

def extend_o(a_list, element):
    a_list.extend(element)
    print('extend:', end = ' ')
    for item in a_list:
        print(item, end = ',')
    print()
append_o(['ab'],'cd')

extend_o(['ab'],'cd')
append_o(['ab'],['cd', 'ef'])
extend_o(['ab'],['cd', 'ef'])
append_o(['ab'],['cd'])
extend_o(['ab'],['cd'])

produces:

append: ab,cd,
extend: ab,c,d,
append: ab,['cd', 'ef'],
extend: ab,cd,ef,
append: ab,['cd'],
extend: ab,cd,

评论

0赞 Shweta Lodha 7/20/2022
You can check out my recoding explaining Extend and Append in Python: youtu.be/8A5ohA-UeiI
0赞 vivek 7/17/2018 #20

Append and extend are one of the extensibility mechanisms in python.

Append: Adds an element to the end of the list.

my_list = [1,2,3,4]

To add a new element to the list, we can use append method in the following way.

my_list.append(5)

The default location that the new element will be added is always in the (length+1) position.

Insert: The insert method was used to overcome the limitations of append. With insert, we can explicitly define the exact position we want our new element to be inserted at.

Method descriptor of insert(index, object). It takes two arguments, first being the index we want to insert our element and second the element itself.

Example: my_list = [1,2,3,4]
my_list[4, 'a']
my_list
[1,2,3,4,'a']

Extend: This is very useful when we want to join two or more lists into a single list. Without extend, if we want to join two lists, the resulting object will contain a list of lists.

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

If we try to access the element at pos 2, we get a list ([3]), instead of the element. To join two lists, we'll have to use append.

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

To join multiple lists

a = [1]
b = [2]
c = [3]
a.extend(b+c)
print (a)
[1,2,3]