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.6sö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_entriesgiriş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_indicesindekslerini 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_indicesve 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( 1bayt) int32_t/ / bit derlemelerinde / int64_t( 4/ 8bayt) arasında değişir )3264
Önceki uygulamada, seyrek bir tür PyDictKeyEntryve boyut dizisi ayrılmak dk_sizezorundaydı; 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( Xboyut boyutuna bağlı olarak) seyrek bir tür dizisinin 2/3 * dk_sizedolu tutulduğu için bu durum böyle değildir. Boş alan türden PyDictKeyEntryolarak değiştirildi intX_t.
Açıkçası, seyrek bir tür dizisi oluşturmak s PyDictKeyEntrydepolamak 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 dictnesne 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.