列表方法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]]

其他回答

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

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的最大区别之一是在函数作用域中使用时,请参阅本文。

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]

追加和扩展是python中的扩展机制之一。

追加:将元素添加到列表末尾。

my_list = [1,2,3,4]

要向列表中添加新元素,我们可以按以下方式使用append方法。

my_list.append(5)

将添加新元素的默认位置始终位于(长度+1)位置。

Insert:Insert方法用于克服append的限制。使用insert,我们可以明确定义新元素插入的确切位置。

insert(索引,对象)的方法描述符。它需要两个参数,第一个是要插入元素的索引,第二个是元素本身。

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

扩展:当我们想将两个或多个列表合并到一个列表中时,这非常有用。如果不使用extend,如果我们想要连接两个列表,那么生成的对象将包含一个列表列表。

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

如果我们试图访问位置2的元素,我们会得到一个列表([3]),而不是元素。要连接两个列表,我们必须使用append。

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

加入多个列表

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

extend()可以与迭代器参数一起使用。这里有一个例子。您希望通过以下方式从列表列表中列出一个列表:

From

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]

列表方法append和extend之间有什么区别?

append将其参数作为单个元素添加到列表末尾。列表本身的长度将增加1。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)

因此,使用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相似。

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

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

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

时间复杂性

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

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

通过多次调用进行迭代以追加会增加复杂性,使其与extend的迭代相当,而且由于extend的循环是在C语言中实现的,因此如果您打算将可迭代项中的连续项追加到列表中,则会更快。

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

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

我们发现,特意创建一个可迭代的just to use extend是(很小的)浪费时间:

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

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

此外,这些时间安排也不那么重要。我只是告诉他们,在Python中,做语义正确的事情就是以正确的方式做事™.

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

结论

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

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