Apakah kamus dipesan dengan Python 3.6+?
Mereka memerintahkan penyisipan [1] . Pada Python 3.6, untuk implementasi Python CPython, kamus mengingat urutan item yang dimasukkan . Ini dianggap sebagai detail implementasi dalam Python 3.6 ; Anda perlu menggunakan OrderedDict
jika Anda ingin pemesanan penyisipan yang dijamin di seluruh implementasi Python lainnya (dan perilaku berurutan lainnya [1] ).
Pada Python 3.7 , ini bukan lagi detail implementasi dan malah menjadi fitur bahasa. Dari pesan python-dev oleh GvR :
Jadikan begitu. "Dict menjaga urutan penyisipan" adalah putusannya. Terima kasih!
Ini berarti bahwa Anda dapat bergantung padanya . Implementasi lain dari Python juga harus menawarkan penyisipan kamus jika mereka ingin menjadi implementasi yang sesuai dari Python 3.7.
Bagaimana 3.6
implementasi kamus Python berkinerja lebih baik [2] dari yang sebelumnya sambil mempertahankan urutan elemen?
Intinya, dengan menjaga dua array .
Array pertama dk_entries
,, menampung entri ( dari jenisPyDictKeyEntry
) untuk kamus sesuai urutan yang dimasukkan. Order pelestarian dicapai dengan menjadi array append saja di mana item baru selalu disisipkan di akhir (urutan penyisipan).
Yang kedua,, dk_indices
memegang indeks untuk dk_entries
array (yaitu, nilai-nilai yang menunjukkan posisi entri yang sesuai di dk_entries
). Array ini bertindak sebagai tabel hash. Ketika kunci di-hash, itu mengarah ke salah satu indeks yang disimpan dk_indices
dan entri yang sesuai diambil dengan mengindeks dk_entries
. Karena hanya indeks yang disimpan, jenis larik ini tergantung pada ukuran keseluruhan kamus (mulai dari jenis int8_t
( 1
byte) hingga int32_t
/ int64_t
( 4
/ 8
byte) di 32
/ 64
bit builds)
Dalam implementasi sebelumnya, berbagai jenis PyDictKeyEntry
dan ukuran dk_size
harus dialokasikan; Sayangnya, itu juga menghasilkan banyak ruang kosong karena array itu tidak boleh lebih dari 2/3 * dk_size
penuh karena alasan kinerja . (dan ruang kosong masih memiliki PyDictKeyEntry
ukuran!).
Ini bukan masalahnya sekarang karena hanya entri yang diperlukan yang disimpan (yang telah dimasukkan) dan jenis array yang jarang intX_t
( X
tergantung pada ukuran dict) 2/3 * dk_size
penuh disimpan. Ruang kosong berubah dari tipe PyDictKeyEntry
ke intX_t
.
Jadi, jelas, membuat array tipe jarang PyDictKeyEntry
jauh lebih banyak menuntut memori daripada array jarang untuk menyimpan int
s.
Anda dapat melihat percakapan lengkap di Python-Dev mengenai fitur ini jika tertarik, ini adalah bacaan yang bagus.
Dalam proposal asli yang dibuat oleh Raymond Hettinger , visualisasi dari struktur data yang digunakan dapat dilihat yang menangkap inti gagasan.
Misalnya, kamus:
d = {'timmy': 'red', 'barry': 'green', 'guido': 'blue'}
saat ini disimpan sebagai [keyhash, key, value]:
entries = [['--', '--', '--'],
[-8522787127447073495, 'barry', 'green'],
['--', '--', '--'],
['--', '--', '--'],
['--', '--', '--'],
[-9092791511155847987, 'timmy', 'red'],
['--', '--', '--'],
[-6480567542315338377, 'guido', 'blue']]
Sebagai gantinya, data harus disusun sebagai berikut:
indices = [None, 1, None, None, None, 0, None, 2]
entries = [[-9092791511155847987, 'timmy', 'red'],
[-8522787127447073495, 'barry', 'green'],
[-6480567542315338377, 'guido', 'blue']]
Seperti yang dapat Anda lihat secara visual sekarang, dalam proposal asli, banyak ruang pada dasarnya kosong untuk mengurangi tabrakan dan membuat pencarian lebih cepat. Dengan pendekatan baru, Anda mengurangi memori yang dibutuhkan dengan menggerakkan sparseness di tempat yang benar-benar diperlukan, dalam indeks.
[1]: Saya katakan "penyisipan memerintahkan" dan tidak "memerintahkan" karena, dengan adanya OrderedDict, "memerintahkan" menunjukkan perilaku lebih lanjut bahwa dict
objek tidak menyediakan . OrderedDicts bersifat reversibel, menyediakan metode sensitif pesanan dan, terutama, memberikan tes kesetaraan pesanan-luas ( ==
, !=
). dict
Saat ini tidak menawarkan perilaku / metode tersebut.
[2]: Implementasi kamus baru menghasilkan ingatan yang lebih baik dengan dirancang lebih kompak; itulah manfaat utama di sini. Dari segi kecepatan, perbedaannya tidak terlalu drastis, ada tempat-tempat dict yang baru mungkin memperkenalkan sedikit kemunduran ( pencarian kunci, misalnya ) sementara di tempat lain (iterasi dan mengubah ukuran muncul dalam pikiran) peningkatan kinerja harus ada.
Secara keseluruhan, kinerja kamus, terutama dalam situasi kehidupan nyata, meningkat karena kekompakan yang diperkenalkan.