Kısa bir python listesine geçmenin deyimsel sözdizimi nedir?
Genellikle Python'daki bir listeye tekrar tekrar eklemek istemezsiniz.
E? Er kısa ve onu çok yapmıyoruz ... Sonra Tamam.
list.insert
Bu list.insert
şekilde kullanılabilir.
list.insert(0, x)
Ancak bu verimsizdir, çünkü Python'da a list
bir işaretçi dizisidir ve Python şimdi listedeki her işaretçiyi almalı ve işaretçiyi ilk yuvaya nesnenize eklemek için birer birer aşağı taşımalıdır, bu yüzden bu gerçekten etkilidir istediğin gibi kısa listeler için.
İşte bunun uygulandığı CPython kaynağından bir pasaj - ve gördüğünüz gibi, dizinin sonunda başlıyoruz ve her ekleme için her şeyi birer birer aşağı taşıyoruz:
for (i = n; --i >= where; )
items[i+1] = items[i];
Önleyen öğelerde etkili olan bir kapsayıcı / liste istiyorsanız, bağlantılı bir liste istersiniz. Python'un başında ve sonunda hızlı bir şekilde eklenebilen çift bağlantılı bir liste var - buna a denir deque
.
deque.appendleft
A collections.deque
, bir liste yönteminin çoğuna sahiptir. list.sort
bir istisna, deque
kesinlikle Liskov'un yerine geçemez list
.
>>> set(dir(list)) - set(dir(deque))
{'sort'}
deque
Aynı zamanda bir yer alır appendleft
yöntemi (aynı zamanda popleft
). Bu deque
, çift uçlu bir kuyruk ve çift bağlantılı bir listedir - uzunluğu ne olursa olsun, bir şeyi önceden eklemek her zaman aynı zaman alır. Büyük O gösterimlerinde, listeler için O (1) ile O (n) arasındaki zaman. İşte kullanımı:
>>> import collections
>>> d = collections.deque('1234')
>>> d
deque(['1', '2', '3', '4'])
>>> d.appendleft('0')
>>> d
deque(['0', '1', '2', '3', '4'])
deque.extendleft
Ayrıca extendleft
, yinelemeli olarak tercih edilen deque'nin yöntemi de geçerlidir :
>>> from collections import deque
>>> d2 = deque('def')
>>> d2.extendleft('cba')
>>> d2
deque(['a', 'b', 'c', 'd', 'e', 'f'])
Her bir öğenin birer birer ekleneceğini ve böylece siparişlerini etkili bir şekilde tersine çevireceğini unutmayın.
list
Karşı performansdeque
Öncelikle, tekrarlayan bazı yinelemeli kurulumlar yapıyoruz:
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
ve performans:
>>> 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 çok daha hızlı. Listeler uzadıkça, bir deque'nin daha iyi performans göstermesini beklerdim. Deque'leri kullanabiliyorsanız extendleft
muhtemelen bu şekilde en iyi performansı elde edersiniz.