Cú pháp thành ngữ để chuẩn bị cho một danh sách python ngắn là gì?
Bạn thường không muốn lặp đi lặp lại một danh sách trong Python.
Nếu nó ngắn và bạn không làm việc đó nhiều ... thì ok.
list.insert
Có list.insertthể được sử dụng theo cách này.
list.insert(0, x)
Nhưng điều này là không hiệu quả, bởi vì trong Python, a listlà một mảng các con trỏ và Python bây giờ phải lấy mọi con trỏ trong danh sách và di chuyển nó xuống một để chèn con trỏ vào đối tượng của bạn trong khe đầu tiên, vì vậy điều này thực sự chỉ hiệu quả cho danh sách khá ngắn, như bạn yêu cầu.
Đây là một đoạn trích từ nguồn CPython , nơi điều này được triển khai - và như bạn có thể thấy, chúng tôi bắt đầu ở cuối mảng và di chuyển mọi thứ xuống một cho mỗi lần chèn:
for (i = n; --i >= where; )
items[i+1] = items[i];
Nếu bạn muốn một thùng chứa / danh sách hiệu quả trong việc chuẩn bị các yếu tố, bạn muốn có một danh sách được liên kết. Python có một danh sách liên kết đôi, có thể chèn vào đầu và cuối một cách nhanh chóng - nó được gọi là a deque.
deque.appendleft
A collections.dequecó nhiều phương pháp của một danh sách. list.sortlà một ngoại lệ, làm cho dequedứt khoát không hoàn toàn thay thế Liskov cho list.
>>> set(dir(list)) - set(dir(deque))
{'sort'}
Các dequecòn có một appendleftphương pháp (cũng như popleft). Đây dequelà một hàng đợi hai đầu và một danh sách liên kết đôi - bất kể độ dài, nó luôn mất cùng một khoảng thời gian để trả trước một cái gì đó. Trong ký hiệu O lớn, O (1) so với thời gian O (n) cho danh sách. Đây là cách sử dụng:
>>> import collections
>>> d = collections.deque('1234')
>>> d
deque(['1', '2', '3', '4'])
>>> d.appendleft('0')
>>> d
deque(['0', '1', '2', '3', '4'])
deque.extendleft
Cũng có liên quan là extendleftphương pháp của deque , mà lặp đi lặp lại:
>>> from collections import deque
>>> d2 = deque('def')
>>> d2.extendleft('cba')
>>> d2
deque(['a', 'b', 'c', 'd', 'e', 'f'])
Lưu ý rằng mỗi phần tử sẽ được đặt trước một phần tử, do đó đảo ngược hiệu quả thứ tự của chúng.
Hiệu suất listso vớideque
Đầu tiên chúng tôi thiết lập với một số lần lặp lại:
import timeit
from collections import deque
def list_insert_0():
l = []
for i in range(20):
l.insert(0, i)
def list_slice_insert():
l = []
for i in range(20):
l[:0] = [i] # semantically same as list.insert(0, i)
def list_add():
l = []
for i in range(20):
l = [i] + l # caveat: new list each time
def deque_appendleft():
d = deque()
for i in range(20):
d.appendleft(i) # semantically same as list.insert(0, i)
def deque_extendleft():
d = deque()
d.extendleft(range(20)) # semantically same as deque_appendleft above
và trình diễn:
>>> min(timeit.repeat(list_insert_0))
2.8267281929729506
>>> min(timeit.repeat(list_slice_insert))
2.5210217320127413
>>> min(timeit.repeat(list_add))
2.0641671380144544
>>> min(timeit.repeat(deque_appendleft))
1.5863927800091915
>>> min(timeit.repeat(deque_extendleft))
0.5352169770048931
Deque nhanh hơn nhiều. Khi các danh sách dài hơn, tôi sẽ mong đợi một deque sẽ thực hiện tốt hơn nữa. Nếu bạn có thể sử dụng deque, extendleftcó lẽ bạn sẽ có được hiệu suất tốt nhất theo cách đó.