Câu hỏi Sự khác biệt giữa các phương thức liệt kê chắp thêm và mở rộng trong Python


Sự khác nhau giữa các phương pháp danh sách append() và extend()?


2690
2017-10-31 05:55


gốc




Các câu trả lời:


append: Gắn thêm đối tượng ở cuối.

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

mang đến cho bạn: [1, 2, 3, [4, 5]]


extend: Mở rộng danh sách bằng cách nối thêm các phần tử từ lặp lại.

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

mang đến cho bạn: [1, 2, 3, 4, 5]


4090
2017-10-31 06:02



Sự khác biệt giữa extend và chỉ cần sử dụng toán tử cộng - trong ví dụ trên, x = x + [4, 5]? - Rohan
Trên thực tế có một sự khác biệt lớn - - x + [4, 5] cung cấp cho bạn một danh sách mới được gán cho x - x.extend() thay đổi danh sách gốc. Tôi xây dựng trong câu trả lời của tôi ở đây dưới đây. - Aaron Hall♦


append thêm phần tử vào danh sách và extend ghép nối danh sách đầu tiên với một danh sách khác (hoặc một danh sách khác có thể lặp lại, không nhất thiết phải là một danh sách.)

>>> li = ['a', 'b', 'mpilgrim', 'z', 'example']
>>> li
['a', 'b', 'mpilgrim', 'z', 'example']

>>> li.append("new")
>>> li
['a', 'b', 'mpilgrim', 'z', 'example', 'new']

>>> li.insert(2, "new")
>>> li
['a', 'b', 'new', 'mpilgrim', 'z', 'example', 'new']

>>> li.extend(["two", "elements"])
>>> li
['a', 'b', 'new', 'mpilgrim', 'z', 'example', 'new', 'two', 'elements']

Từ Nhảy vào Python.


525
2017-10-31 05:57





Sự khác biệt giữa các phương pháp liệt kê phụ thêm và mở rộng là gì?

  • append thêm đối số của nó như là một phần tử duy nhất vào cuối danh sách. Độ dài của danh sách sẽ tăng lên một.
  • extend lặp lại đối số của nó thêm từng phần tử vào danh sách, mở rộng danh sách. Độ dài của danh sách sẽ tăng theo tuy nhiên nhiều phần tử nằm trong đối số có thể lặp lại.

append

Các list.append phương thức nối một đối tượng vào cuối danh sách.

my_list.append(object) 

Dù đối tượng là gì, dù là một số, một chuỗi, một danh sách khác hay một thứ gì khác, nó sẽ được thêm vào cuối my_list như một mục duy nhất trong danh sách.

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

Vì vậy, hãy nhớ rằng một danh sách là một đối tượng. Nếu bạn nối thêm một danh sách khác vào danh sách, danh sách đầu tiên sẽ là một đối tượng duy nhất ở cuối danh sách (có thể không phải là thứ bạn muốn):

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

extend

Các list.extend phương pháp mở rộng danh sách bằng cách nối thêm các phần tử từ một lần lặp:

my_list.extend(iterable)

Vì vậy, với mở rộng, mỗi phần tử của iterable được nối vào danh sách. Ví dụ:

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

Hãy nhớ rằng một chuỗi là một iterable, vì vậy nếu bạn mở rộng một danh sách với một chuỗi, bạn sẽ nối thêm mỗi ký tự khi bạn lặp qua chuỗi (có thể không phải là những gì bạn muốn):

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

Vận hành quá tải, __add__, (+) và __iadd__ (+=)

Cả hai + và += toán tử được định nghĩa cho list. Họ có ngữ nghĩa tương tự như mở rộng.

my_list + another_list tạo ra một danh sách thứ ba trong bộ nhớ, vì vậy bạn có thể trả về kết quả của nó, nhưng nó đòi hỏi rằng iterable thứ hai là một danh sách.

my_list += another_list sửa đổi danh sách tại chỗ (nó  toán tử tại chỗ và danh sách là các đối tượng có thể thay đổi, như chúng ta đã thấy) để nó không tạo danh sách mới. Nó cũng hoạt động như mở rộng, trong đó lặp lại thứ hai có thể là bất kỳ loại lặp nào.

Đừng bối rối - my_list = my_list + another_list không tương đương với += - nó cung cấp cho bạn một danh sách hoàn toàn mới được gán cho my_list.

Độ phức tạp thời gian

Đã thêm độ phức tạp thời gian không đổi, O (1).

Mở rộng có độ phức tạp thời gian, O (k).

Lặp lại qua nhiều cuộc gọi đến append thêm vào sự phức tạp, làm cho nó tương đương với mở rộng, và kể từ khi lặp đi lặp lại của mở rộng được thực hiện trong C, nó sẽ luôn luôn được nhanh hơn nếu bạn có ý định nối thêm các mục liên tiếp từ một iterable vào một danh sách.

Hiệu suất

Bạn có thể tự hỏi những gì có hiệu quả hơn, vì chắp thêm có thể được sử dụng để đạt được kết quả tương tự như mở rộng. Các chức năng sau thực hiện tương tự:

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

def extend(alist, iterable):
    alist.extend(iterable)

Vì vậy, hãy dành thời gian cho họ:

import timeit

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

Giải quyết nhận xét về thời gian

Một bình luận viên nói:

Câu trả lời hoàn hảo, tôi chỉ bỏ lỡ thời gian so sánh chỉ thêm một phần tử

Làm điều đúng ngữ nghĩa. Nếu bạn muốn nối thêm tất cả các phần tử trong một lần lặp lại, hãy sử dụng extend. Nếu bạn chỉ cần thêm một phần tử, hãy sử dụng append.

Ok, vì vậy, hãy tạo một thử nghiệm để xem cách hoạt động này đúng lúc:

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

Và chúng ta thấy rằng đi ra khỏi con đường của chúng tôi để tạo ra một iterable chỉ để sử dụng mở rộng là một (nhỏ) lãng phí thời gian:

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

Chúng tôi học hỏi từ điều này mà không có gì thu được từ việc sử dụng extend khi chúng tôi chỉ có một để thêm phần tử.

Ngoài ra, những thời gian này không quan trọng. Tôi chỉ cho họ thấy rằng, trong Python, làm điều đúng ngữ nghĩa là làm mọi thứ Đúng Đường.

Có thể hiểu rằng bạn có thể kiểm tra thời gian trên hai hoạt động có thể so sánh và nhận được kết quả mơ hồ hoặc ngược lại. Chỉ cần tập trung vào làm điều đúng ngữ nghĩa.

Phần kết luận

Chúng ta thấy rằng extend là ngữ nghĩa rõ ràng hơn, và nó có thể chạy nhanh hơn nhiều append, khi bạn định chắp thêm từng phần tử trong một lần lặp lại vào danh sách. 

Nếu bạn chỉ có một phần tử duy nhất (không phải trong một vòng lặp) để thêm vào danh sách, hãy sử dụng append.


268
2018-01-23 22:44



Câu trả lời hoàn hảo, tôi chỉ bỏ lỡ thời gian so sánh chỉ thêm một phần tử - David Sánchez
@Aaron Hall Một bình luận nhỏ trong thuật toán cho thời gian. "extend_one" có thể trả về "hơi sai" thời gian vì việc tạo danh sách cũng có liên quan. Có lẽ tốt hơn là tạo các mục dưới dạng biến (ex1 = 0 và ex2 = [0]) và chuyển các biến này, nếu bạn muốn nghiêm ngặt hơn. - ilias iliadis
Câu trả lời hoàn hảo thực sự. Điều gì về hiệu suất của l1 += l2 so với l1.extend(l2)? - Jean-Francois T.


append nối thêm một phần tử. extend nối thêm một danh sách các phần tử.

Lưu ý rằng nếu bạn chuyển danh sách để nối thêm, nó vẫn thêm một phần tử:

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

92
2017-10-31 05:57





Hai đoạn sau đây tương đương ngữ nghĩa:

for item in iterator:
    a_list.append(item)

a_list.extend(iterator)

Sau này có thể nhanh hơn khi vòng lặp được thực hiện trong C.


42
2017-08-20 21:11



Mở rộng là ~ 4x nhanh hơn trên máy tính của tôi hơn là nối thêm vào một vòng lặp (16us so với 4us cho 100 vòng 0) - Alex L
extend() có lẽ preallocates, trong khi append() có khả năng không. - Mad Physicist


Bạn có thể sử dụng "+" để trả về mở rộng, thay vì mở rộng tại chỗ.

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]

Tương tự += cho hành vi tại chỗ, nhưng với sự khác biệt nhỏ từ append & extend. Một trong những khác biệt lớn nhất của += từ append và extend là khi nó được sử dụng trong phạm vi chức năng, hãy xem bài đăng trên blog này.


29
2017-08-26 11:21



Việc sử dụng '+' để trả về mở rộng có ảnh hưởng đến độ phức tạp của thời gian không? - franklin
@franklin, xem câu trả lời này để biết chi tiết: stackoverflow.com/a/28119966/2230844 - denfromufa
Tôi không thấy cách này trả lời câu hỏi - ppperry


Phương thức append () thêm một mục vào cuối danh sách.

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

Phương thức extend () lấy một đối số, một danh sách và nối thêm từng mục của đối số vào danh sách gốc. (Danh sách được thực hiện như các lớp. "Tạo" một danh sách thực sự khởi tạo một lớp. Như vậy, danh sách có các phương thức hoạt động trên đó.)

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

Từ Lặn vào Python.


29
2017-10-31 13:12



Bạn không thể mở rộng chỉ với 6 vì nó không thể lặp lại được. Và đầu ra thứ hai trong ví dụ của bạn là sai. 'abc' được thêm dưới dạng một phần tử duy nhất kể từ khi bạn chuyển nó vào extend dưới dạng danh sách có một phần tử ['abc']: [1, 2, 3, 4, 5, 'abc']. Để làm cho kết quả ví dụ của bạn chính xác, hãy thay đổi dòng abc thành: x.extend('abc'). Và loại bỏ x.extend(6) hoặc thay đổi nó thành x.extend([6]). - aneroid


 Nối và mở rộng

enter image description here

Với phụ thêm, bạn có thể nối thêm một phần tử đơn lẻ sẽ mở rộng danh sách:

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

Nếu bạn muốn mở rộng nhiều hơn một phần tử, bạn nên sử dụng mở rộng, bởi vì bạn chỉ có thể nối thêm một danh sách hoặc một danh sách phần tử:

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

Để bạn có danh sách lồng nhau

Thay vào đó với mở rộng, bạn có thể mở rộng một phần tử như thế này

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

Hoặc, khác với phụ thêm, mở rộng nhiều phần tử hơn trong một lần mà không lồng vào danh sách thành phần tử gốc (đó là lý do mở rộng tên)

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

 Thêm một phần tử với cả hai phương thức

enter image description here

 nối thêm 1 phần tử

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

 mở rộng một phần tử

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

 Thêm các yếu tố khác ... với các kết quả khác nhau

Nếu bạn sử dụng phụ thêm cho nhiều hơn một phần tử, bạn phải chuyển danh sách các phần tử làm đối số và bạn sẽ nhận được một danh sách NESTED!

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

Với mở rộng, thay vào đó, bạn chuyển một danh sách làm đối số, nhưng bạn sẽ nhận được một danh sách với phần tử mới không được lồng trong danh sách cũ.

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

Vì vậy, với nhiều yếu tố, bạn sẽ sử dụng mở rộng để có được một danh sách với nhiều mục hơn. Bạn sẽ sử dụng chắp thêm, để nối thêm các phần tử không vào danh sách, nhưng một phần tử là một danh sách lồng nhau như bạn có thể thấy rõ trong đầu ra của mã.

enter image description here

enter image description here


17
2017-10-18 07:33



Đây là câu trả lời hay nhất - Billal BEGUERADJ


append(object) - Cập nhật danh sách bằng cách thêm một đối tượng vào danh sách.

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) - Về cơ bản nối hai danh sách.

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]

16
2018-05-12 19:51