Sözlükler Python 3.6 ve sonraki sürümlerinde sıralanıyor mu?
Bunlar olan ekleme sipariş [1] . Python 3.6'dan itibaren, Python'un CPython uygulaması için sözlükler eklenen öğelerin sırasını hatırlar . Bu Python 3.6'da bir uygulama detayı olarak kabul edilir ; diğer Python uygulamalarında (ve diğer sıralı davranışlarda [1] ) garanti edilenOrderedDict
ekleme siparişi vermek istiyorsanız kullanmanız gerekir .
Python 3.7'den itibaren , bu artık bir uygulama detayı değildir ve bunun yerine bir dil özelliği haline gelir. GvR'nin bir python-dev mesajından :
Öyleyse yap. "Dict ekleme emrini koruyor" kararıdır. Teşekkürler!
Bu basitçe ona güvenebileceğiniz anlamına gelir . Python'un diğer uygulamaları da, Python 3.7'nin uygun bir uygulaması olmak istiyorlarsa, kampanya siparişi verilmiş bir sözlük sunmalıdır.
Python 3.6
sözlük uygulaması , öğe sırasını koruyarak eskisinden daha iyi nasıl çalışır [2] ?
Esasen, iki dizi tutarak .
İlk dizi, sözlüğün dk_entries
girişlerini ( türündePyDictKeyEntry
) eklendikleri sırayla tutar. Koruma sırası, sonunda yalnızca yeni öğelerin her zaman sonuna eklendiği bir ekleme dizisi (ekleme sırası) ile gerçekleştirilir.
İkincisi,, dizinin dk_indices
indekslerini tutar dk_entries
(yani, ilgili girişin konumunu gösteren değerler dk_entries
). Bu dizi karma tablosu olarak işlev görür. Bir anahtar karma olduğunda, depolanan endekslerden birine yol açar dk_indices
ve karşılık gelen giriş indeksleme ile getirilir dk_entries
. Yalnızca dizinler tutulduğundan, bu dizinin türü sözlüğün toplam boyutuna bağlıdır (tür int8_t
( 1
bayt) int32_t
/ / bit derlemelerinde / int64_t
( 4
/ 8
bayt) arasında değişir )32
64
Önceki uygulamada, seyrek bir tür PyDictKeyEntry
ve boyut dizisi ayrılmak dk_size
zorundaydı; maalesef, bu dizinin performans nedenleriyle2/3 * dk_size
dolu olmasından daha fazla olmasına izin verilmediğinden, çok fazla boş alanla sonuçlandı . (ve boş alanın büyüklüğü hala vardı !).PyDictKeyEntry
Sadece gerekli girdiler (eklenmiş olanlar) depolandığından ve intX_t
( X
boyut boyutuna bağlı olarak) seyrek bir tür dizisinin 2/3 * dk_size
dolu tutulduğu için bu durum böyle değildir. Boş alan türden PyDictKeyEntry
olarak değiştirildi intX_t
.
Açıkçası, seyrek bir tür dizisi oluşturmak s PyDictKeyEntry
depolamak için seyrek bir diziden çok daha fazla bellek gerektirir int
.
İlgileniyorsanız, bu özellikle ilgili Python-Dev ile ilgili tüm konuşmayı görebilirsiniz, iyi bir okuma.
Raymond Hettinger tarafından yapılan orijinal teklifte , kullanılan veri yapılarının, fikrin özünü yakalayan bir görselleştirmesi görülebilir.
Örneğin, sözlük:
d = {'timmy': 'red', 'barry': 'green', 'guido': 'blue'}
şu anda [keyhash, key, value] olarak depolanıyor:
entries = [['--', '--', '--'],
[-8522787127447073495, 'barry', 'green'],
['--', '--', '--'],
['--', '--', '--'],
['--', '--', '--'],
[-9092791511155847987, 'timmy', 'red'],
['--', '--', '--'],
[-6480567542315338377, 'guido', 'blue']]
Bunun yerine, veriler aşağıdaki gibi organize edilmelidir:
indices = [None, 1, None, None, None, 0, None, 2]
entries = [[-9092791511155847987, 'timmy', 'red'],
[-8522787127447073495, 'barry', 'green'],
[-6480567542315338377, 'guido', 'blue']]
Gördüğünüz gibi, orijinal teklifte, çarpışmaları azaltmak ve aramaları daha hızlı yapmak için çok fazla alan boş. Yeni yaklaşımla, seyrekliği gerçekten gerekli olduğu yerlerde, endekslerde taşıyarak gereken belleği azaltırsınız.
[1]: I "ekleme sipariş" olup OrderedDict varlığı ile, "düzenli", çünkü bu daha davranışını göstermektedir "sıralı" demek dict
nesne sağlamaz . SıralıDikkatler tersine çevrilebilir, siparişe duyarlı yöntemler sağlar ve esas olarak siparişe duyarlı bir eşitlik testi sağlar ( ==
, !=
). dict
şu anda bu davranışlardan / yöntemlerden hiçbirini sunmuyor.
[2]: Yeni sözlük uygulamaları daha kompakt bir şekilde tasarlanarak daha iyi bellek performansı sağlar ; buradaki ana fayda bu. Hız açısından, fark çok sert değil, yeni diktinin hafif gerilemeler ( örneğin anahtar aramaları ) getirebileceği yerler varken, diğerlerinde (yineleme ve yeniden boyutlandırma akla geliyor) bir performans artışı olmalıdır.
Genel olarak, sözlüğün performansı, özellikle gerçek yaşamdaki durumlarda, sunulan kompaktlık nedeniyle iyileşir.