Hướng dẫn what to use instead of append in python - sử dụng cái gì thay vì nối thêm trong python

Sự khác biệt giữa các phương thức danh sách nối và mở rộng là gì?

  • >>> my_list
    ['foo', 'bar']
    >>> my_list.append('baz')
    >>> my_list
    ['foo', 'bar', 'baz']
    
    1 thêm đối số của nó như một yếu tố duy nhất vào cuối danh sách. Độ dài của danh sách sẽ tăng thêm một.
  • >>> my_list
    ['foo', 'bar']
    >>> my_list.append('baz')
    >>> my_list
    ['foo', 'bar', 'baz']
    
    2 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 lên bởi nhiều yếu tố là trong đối số có thể lặp lại.

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

Phương thức

>>> my_list
['foo', 'bar']
>>> my_list.append('baz')
>>> my_list
['foo', 'bar', 'baz']
4 nối thêm một đối tượng vào cuối danh sách.

my_list.append(object) 

Dù đối tượng là gì, cho dù là một số, một chuỗi, một danh sách khác hoặc một cái gì đó khác, nó được thêm vào cuối

>>> my_list
['foo', 'bar']
>>> my_list.append('baz')
>>> my_list
['foo', 'bar', 'baz']
5 dưới dạng một mục nhập 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 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à điều bạn muốn):

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

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

Phương pháp

>>> my_list
['foo', 'bar']
>>> my_list.append('baz')
>>> my_list
['foo', 'bar', 'baz']
7 mở rộng danh sách bằng cách nối thêm các phần tử từ một điều khác nhau:

my_list.extend(iterable)

Vì vậy, với phần mở rộng, mỗi yếu tố của Iterable được thêm 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 thứ có thể đi được, vì vậy nếu bạn mở rộng một danh sách với một chuỗi, bạn sẽ thêm từng ký tự khi bạn lặp lại chuỗi (có thể không phải là điều bạn muốn):

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

Quá tải người vận hành, >>> my_list ['foo', 'bar'] >>> my_list.append('baz') >>> my_list ['foo', 'bar', 'baz'] 8 (>>> my_list ['foo', 'bar'] >>> my_list.append('baz') >>> my_list ['foo', 'bar', 'baz'] 9) và >>> 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. 0 (>>> 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. 1)

Cả hai toán tử

>>> my_list
['foo', 'bar']
>>> my_list.append('baz')
>>> my_list
['foo', 'bar', 'baz']
9 và
>>> 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.
1 đều được xác định cho
>>> 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.
4. Chúng giống nhau về mặt ngữ nghĩa với mở rộng.

>>> 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.
5 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ó yêu cầu rằng có thể đi được thứ hai là một danh sách.

>>> 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.
6 sửa đổi danh sách tại chỗ (nó là 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 ra một danh sách mới. Nó cũng hoạt động như mở rộng, trong đó thứ hai có thể là bất kỳ loại khác.

Đừng nhầm lẫn -

>>> 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.
7 không tương đương với
>>> 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.
1 - 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 về thời gian

Phụ lục có độ phức tạp thời gian không đổi (khấu hao), O (1).

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

Lặp đi lặp lại thông qua nhiều cuộc gọi đến

>>> my_list
['foo', 'bar']
>>> my_list.append('baz')
>>> my_list
['foo', 'bar', 'baz']
1 làm tăng thêm sự phức tạp, làm cho nó tương đương với phần mở rộng và vì lần lặp mở rộng được triển khai trong C, nó sẽ luôn nhanh hơn nếu bạn có ý định nối các mục liên tiếp từ một danh sách có thể sử dụng.

Liên quan đến "khấu hao" - từ Danh sách đối tượng Thực hiện Nguồn:

    /* 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().

Điều này có nghĩa là chúng tôi nhận được những lợi ích của việc phân bổ bộ nhớ lớn hơn so với việc phân bổ bộ nhớ cần thiết ở phía trước, nhưng chúng tôi có thể trả tiền cho việc phân bổ lại cận biên tiếp theo với một phiên bản thậm chí còn lớn hơn. Tổng thời gian cho tất cả các ứng dụng là tuyến tính tại O (N) và thời gian đó được phân bổ cho mỗi lần phụ, trở thành O (1).

Màn biểu diễn

Bạn có thể tự hỏi những gì là hiệu suất hơn, vì có thể sử dụng thêm để đạt được kết quả tương tự như mở rộng. Các chức năng sau đây làm điều 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 đến lúc họ:

import timeit

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

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

Một người bình luậ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 yếu tố

Làm điều chính xác về mặt ngữ nghĩa. Nếu bạn muốn nối tất cả các yếu tố trong một điều đó, hãy sử dụng

>>> my_list
['foo', 'bar']
>>> my_list.append('baz')
>>> my_list
['foo', 'bar', 'baz']
2. Nếu bạn chỉ thêm một phần tử, hãy sử dụng
>>> my_list
['foo', 'bar']
>>> my_list.append('baz')
>>> my_list
['foo', 'bar', 'baz']
1.

OK, vì vậy hãy tạo một thử nghiệm để xem cách thức hoạt động của nó đú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 tôi thấy rằng việc đi ra khỏi con đường của chúng tôi để tạo ra một sự khác biệt chỉ để sử dụng mở rộng là một sự lãng phí thời gian (nhỏ):

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

Chúng tôi học được từ điều này rằng không có gì đạt được từ việc sử dụng

>>> my_list
['foo', 'bar']
>>> my_list.append('baz')
>>> my_list
['foo', 'bar', 'baz']
2 khi chúng tôi chỉ có một yếu tố để nối thêm.

Ngoài ra, những thời điểm này không quan trọng. Tôi chỉ cho họ thấy để đưa ra quan điểm rằng, trong Python, làm điều chính xác về mặt ngữ nghĩa là làm mọi thứ đúng cách ™.

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

Sự kết luận

Chúng tôi thấy rằng

>>> my_list
['foo', 'bar']
>>> my_list.append('baz')
>>> my_list
['foo', 'bar', 'baz']
2 rõ ràng hơn về mặt ngữ nghĩa và nó có thể chạy nhanh hơn nhiều so với
>>> my_list
['foo', 'bar']
>>> my_list.append('baz')
>>> my_list
['foo', 'bar', 'baz']
1, khi bạn có ý định nối từng phần tử trong một danh sách.

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

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