Perangkat dan dikte dioptimalkan untuk berbagai kasus penggunaan. Penggunaan utama dari set adalah pengujian keanggotaan cepat, yang merupakan pesanan agnostik.Untuk dicts, biaya pencarian adalah operasi yang paling kritis, dan kuncinya lebih mungkin ada. Dengan set, ada atau tidaknya elemen tidak diketahui sebelumnya, dan implementasi set perlu dioptimalkan untuk kasus yang ditemukan dan tidak ditemukan. Juga, beberapa optimisasi untuk operasi himpunan umum seperti union dan persimpangan membuat sulit untuk mempertahankan pemesanan himpunan tanpa menurunkan kinerja.
Sementara kedua struktur data berdasarkan hash, itu adalah kesalahpahaman umum bahwa set hanya diimplementasikan sebagai dikts dengan nilai nol. Bahkan sebelum implementasi dict kompak dalam CPython 3.6, implementasi set dan dict sudah berbeda secara signifikan, dengan sedikit kode yang digunakan kembali. Misalnya, dicts menggunakan probing acak, tetapi set menggunakan kombinasi linear probing dan open addressing, untuk meningkatkan lokalitas cache. Probe linear awal (default 9 langkah dalam CPython) akan memeriksa serangkaian pasangan kunci / hash yang berdekatan, meningkatkan kinerja dengan mengurangi biaya penanganan benturan hash - akses memori berturut-turut lebih murah daripada probe yang tersebar.
Secara teori dimungkinkan untuk mengubah implementasi himpunan CPython menjadi serupa dengan dikt kompak, tetapi dalam praktiknya ada kelemahan, dan pengembang inti terkenal menentang untuk melakukan perubahan semacam itu.
Set tetap tidak teratur. (Mengapa? Pola penggunaannya berbeda. Juga, implementasinya berbeda.)
- Guido van Rossum
Set menggunakan algoritma yang berbeda yang tidak dapat diubah untuk mempertahankan urutan penyisipan. Operasi set-ke-set kehilangan fleksibilitas dan optimalisasi jika diperlukan. Himpunan matematika didefinisikan dalam hal himpunan tidak teratur. Singkatnya, mengatur pemesanan tidak dalam waktu dekat.
- Raymond Hettinger
Diskusi terperinci tentang apakah akan memadatkan set untuk 3.7, dan jawaban tentang mengapa diputuskan menentang, dapat ditemukan di milis python-dev.
Singkatnya, poin utama adalah bahwa pola penggunaannya berbeda (perintah pemesanan penyisipan seperti ** kwarg berguna , kurang begitu untuk set), penghematan ruang untuk set compacting kurang signifikan (karena hanya ada kunci dan array hash untuk densifikasi, tidak seperti kunci, hash dan nilai), dan optimisasi probing linier dalam set tidak sesuai dengan implementasi yang kompak.
Saya akan mereproduksi posting Raymond di bawah ini yang mencakup poin paling penting.
Pada 14 Sep 2016, pada jam 15:50, Eric Snow menulis:
Lalu, saya akan melakukan hal yang sama untuk set.
Kecuali saya salah paham, Raymond menentang untuk melakukan perubahan yang sama dengan pengaturan.
Betul. Berikut adalah beberapa pemikiran tentang masalah ini sebelum orang mulai berlari liar.
Untuk dikt kompak, penghematan ruang adalah kemenangan bersih dengan ruang tambahan yang dikonsumsi oleh indeks dan alokasi keseluruhan untuk array kunci / nilai / hash lebih dari diimbangi oleh peningkatan kepadatan array kunci / nilai / hash. Namun untuk set, net jauh lebih tidak menguntungkan karena kita masih membutuhkan indeks dan alokasi keseluruhan tetapi hanya dapat mengimbangi biaya ruang dengan memadatkan hanya dua dari tiga array. Dengan kata lain, pemadatan lebih masuk akal ketika Anda telah menyia-nyiakan ruang untuk kunci, nilai, dan hash. Jika Anda kehilangan salah satu dari ketiganya, itu berhenti memaksa.
Pola penggunaan untuk set berbeda dengan dikt. Yang pertama memiliki lebih banyak hit atau miss lookup. Yang terakhir cenderung memiliki lebih sedikit pencarian kunci yang hilang. Selain itu, beberapa optimisasi untuk operasi set-to-set membuatnya sulit untuk mempertahankan urutan pemesanan tanpa mempengaruhi kinerja.
Saya mengejar jalur alternatif untuk meningkatkan kinerja yang ditetapkan. Alih-alih memadatkan (yang tidak banyak ruang menang dan mengeluarkan biaya tipuan tambahan), saya menambahkan linear probing untuk mengurangi biaya tabrakan dan meningkatkan kinerja cache. Peningkatan ini tidak sesuai dengan pendekatan pemadatan yang saya anjurkan untuk kamus.
Untuk saat ini, efek samping pemesanan pada kamus tidak dijamin, jadi terlalu dini untuk mulai bersikeras bahwa set juga dipesan. Dokumen sudah ditautkan ke resep untuk membuat OrderedSet ( https://code.activestate.com/recipes/576694/ ) tetapi sepertinya serapannya
hampir nol. Juga, sekarang Eric Snow telah memberi kami OrderedDict cepat, lebih mudah dari sebelumnya untuk membuat OrderedSet dari MutableSet dan OrderedDict, tapi sekali lagi saya belum melihat minat nyata karena analisis data set-to-set yang khas tidak benar-benar perlu atau peduli tentang pemesanan. Demikian juga, penggunaan utama pengujian keanggotaan cepat adalah pesanan agnostik.
Yang mengatakan, saya pikir ada ruang untuk menambahkan implementasi set alternatif ke PyPI. Secara khusus, ada beberapa kasus khusus yang menarik untuk data yang dapat dipesan di mana operasi set-to-set dapat dipercepat dengan membandingkan seluruh rentang kunci (lihat
https://code.activestate.com/recipes/230113-implementation-of- set-using-sort-list
untuk titik awal). IIRC, PyPI sudah memiliki kode untuk filter bloom set-seperti dan hashing cuckoo.
Saya memahami bahwa menarik untuk memiliki blok kode utama yang diterima ke dalam inti Python tetapi itu seharusnya tidak terbuka bagi pintu air untuk terlibat dalam penulisan ulang yang lebih utama dari tipe data lain kecuali kami yakin itu dijamin.
- Raymond Hettinger
Dari [Python-Dev] Python 3.6 dict menjadi ringkas dan mendapatkan versi pribadi; dan kata kunci dipesan , September 2016.