Penambahan collections.defaultdict
di Python 2.5 sangat mengurangi kebutuhan untuk dict
's setdefault
metode. Pertanyaan ini untuk pendidikan kolektif kita:
- Apa yang
setdefault
masih berguna untuk hari ini di Python 2.6 / 2.7? - Kasus penggunaan populer apa
setdefault
yang digantikancollections.defaultdict
?
python
dictionary
setdefault
Eli Bendersky
sumber
sumber
Jawaban:
Bisa dibilang
defaultdict
berguna untuk pengaturan default sebelum mengisi dict dansetdefault
berguna untuk pengaturan default saat atau setelah mengisi dict .Mungkin kasus penggunaan yang paling umum: Mengelompokkan item (dalam data yang tidak disortir, gunakan yang lain
itertools.groupby
)Terkadang Anda ingin memastikan bahwa kunci tertentu ada setelah membuat dict.
defaultdict
tidak berfungsi dalam hal ini, karena hanya membuat kunci pada akses eksplisit. Pikirkan Anda menggunakan sesuatu HTTP-ish dengan banyak header - beberapa opsional, tetapi Anda ingin default untuk mereka:sumber
defaultdict
. Bisakah Anda memberikan contoh tentang apa yang Anda maksud dalam paragraf pertama?setdefault
. Adefaultdict
di sisi lain tidak akan berfungsi jika tidak semuadefaultvalues
sama (yaitu ada beberapa0
dan beberapa ada[]
).headers = dict(optional_headers)
. Untuk kasus ketika nilai default tidak semuanya sama. Dan hasil akhirnya sama seperti jika Anda mendapatkan header HTTP terlebih dahulu kemudian atur default untuk yang tidak Anda dapatkan. Dan itu cukup berguna jika Anda sudah memilikinyaoptional_headers
. Coba kode 2 langkah saya yang diberikan dan bandingkan dengan kode Anda, dan Anda akan mengerti maksud saya.new.setdefault(key, []).append(value)
defaultdict
adalah lebih baik daripadasetdefault
(jadi di mana use case sekarang?). Juga,ChainMap
akan lebih baik menanganihttp
contohnya, IMO.Saya biasanya menggunakan
setdefault
untuk argumen argumen kata kunci, seperti dalam fungsi ini:Ini bagus untuk mengubah argumen dalam pembungkus di sekitar fungsi yang mengambil argumen kata kunci.
sumber
defaultdict
bagus ketika nilai defaultnya statis, seperti daftar baru, tetapi tidak terlalu banyak jika itu dinamis.Sebagai contoh, saya perlu kamus untuk memetakan string ke int unik.
defaultdict(int)
akan selalu menggunakan 0 untuk nilai default. Juga,defaultdict(intGen())
selalu menghasilkan 1.Sebagai gantinya, saya menggunakan dict biasa:
Catatan yang
dict.get(key, nextID())
tidak mencukupi karena saya harus dapat merujuk ke nilai-nilai ini nanti.intGen
adalah kelas kecil yang saya bangun yang secara otomatis menambah int dan mengembalikan nilainya:Jika seseorang memiliki cara untuk melakukan ini dengan
defaultdict
saya ingin melihatnya.sumber
intGen
denganitertools.count().next
.nextID()
Nilai akan bertambah setiap kalimyDict.setdefault()
dipanggil, meskipun nilai yang dikembalikan tidak digunakan sebagaistrID
. Ini sepertinya boros dan menggambarkan salah satu hal yang tidak saya sukaisetdefault()
secara umum - yaitu selalu mengevaluasidefault
argumennya apakah benar-benar digunakan atau tidak.defaultdict
:myDict = defaultdict(lambda: nextID())
. Nanti,strID = myDict[myStr]
di loop.myDict = defaultdict(nextID)
?Saya menggunakan
setdefault()
ketika saya ingin nilai default dalam sebuahOrderedDict
. Tidak ada koleksi Python standar yang tidak baik, tetapi ada yang cara untuk menerapkan koleksi tersebut.sumber
Karena sebagian besar jawaban menyatakan
setdefault
ataudefaultdict
akan membiarkan Anda menetapkan nilai default saat kunci tidak ada. Namun, saya ingin menunjukkan peringatan kecil sehubungan dengan kasus penggunaansetdefault
. Ketika interpreter Python dijalankan,setdefault
ia akan selalu mengevaluasi argumen kedua ke fungsi bahkan jika kunci ada dalam kamus Sebagai contoh:Seperti yang Anda lihat,
print
juga dieksekusi meskipun 2 sudah ada dalam kamus. Ini menjadi sangat penting jika Anda berencana untuk menggunakansetdefault
misalnya untuk optimasi sepertimemoization
. Jika Anda menambahkan pemanggilan fungsi rekursif sebagai argumen keduasetdefault
, Anda tidak akan mendapatkan kinerja dari itu karena Python akan selalu memanggil fungsi secara rekursif.Karena memoisasi disebutkan, alternatif yang lebih baik adalah menggunakan functools.lru_cache dekorator jika Anda mempertimbangkan untuk meningkatkan fungsi dengan memoisasi. lru_cache menangani persyaratan caching untuk fungsi rekursif yang lebih baik.
sumber
Seperti yang dikatakan Muhammad, ada situasi di mana Anda hanya kadang-kadang ingin menetapkan nilai default. Contoh yang bagus dari hal ini adalah struktur data yang pertama kali dihuni, kemudian dipertanyakan.
Pertimbangkan trie. Saat menambahkan kata, jika subnode diperlukan tetapi tidak ada, itu harus dibuat untuk memperpanjang trie. Saat menanyakan keberadaan kata, subnode yang hilang menunjukkan bahwa kata tersebut tidak ada dan tidak boleh dibuat.
Keputusan default tidak dapat melakukan ini. Sebagai gantinya, dikte reguler dengan metode get dan setdefault harus digunakan.
sumber
Secara teoritis,
setdefault
akan tetap berguna jika Anda terkadang ingin menetapkan default dan terkadang tidak. Dalam kehidupan nyata, saya belum menemukan kasus penggunaan seperti itu.Namun, use case yang menarik muncul dari pustaka standar (Python 2.6, _threadinglocal.py):
Saya akan mengatakan bahwa menggunakan
__dict__.setdefault
adalah kasus yang sangat berguna.Sunting : Ketika itu terjadi, ini adalah satu-satunya contoh di perpustakaan standar dan itu dalam komentar. Jadi mungkin itu tidak cukup kasus untuk membenarkan keberadaan
setdefault
. Namun, berikut ini penjelasannya:Objek menyimpan atributnya di dalam
__dict__
atribut. Ketika itu terjadi,__dict__
atribut dapat ditulisi kapan saja setelah pembuatan objek. Ini juga merupakan kamus, bukan adefaultdict
. Hal ini tidak masuk akal untuk objek dalam kasus umum untuk memiliki__dict__
sebagaidefaultdict
karena itu akan membuat setiap objek memiliki semua pengidentifikasi hukum sebagai atribut. Jadi saya tidak bisa melihat adanya perubahan pada objek Python yang bisa dihilangkan__dict__.setdefault
, selain menghapusnya sama sekali jika dianggap tidak berguna.sumber
__dict__
adalah dengan implementasi adict
, bukan adefaultdict
.setdefault
tinggal di Python, tetapi ingin tahu bahwa sekarang hampir tidak berguna.setdefault
membuat eksplisit bahwa Anda menetapkan ke suatu dikt melalui kunci yang mungkin atau mungkin tidak ada, dan jika tidak ada Anda ingin itu dibuat dengan nilai default: misalnyad.setdefault(key,[]).append(value)
. Di tempat lain dalam program ini Anda melakukan dialist=d[k]
mana k dihitung, dan Anda ingin pengecualian dilemparkan jika k di tidak dalam d (yang dengan defaultdict mungkin memerlukanassert k in d
atau bahkanif not ( k in d): raise KeyError
Salah satu kelemahan
defaultdict
overdict
(dict.setdefault
) adalah bahwadefaultdict
objek membuat item baru SETIAP SAAT kunci yang tidak ada diberikan (misalnya dengan==
,print
). Jugadefaultdict
kelas umumnya jauh lebih umum daripadadict
kelas, lebih sulit untuk membuat serialisasi IME-nya.Fungsi IMO PS | metode tidak dimaksudkan untuk memutasikan suatu objek, tidak boleh bermutasi suatu objek.
sumber
defaultdict(lambda l=[]: l)
.Berikut adalah beberapa contoh setdefault untuk menunjukkan manfaatnya:
sumber
Saya menulis ulang jawaban yang diterima dan memfasilitasi untuk pemula.
Selain itu, saya mengkategorikan metode sebagai referensi:
sumber
Saya sering menggunakan setdefault ketika, dapatkan ini, menetapkan default (!!!) dalam kamus; agak umum kamus os.environ:
Kurang ringkas, ini terlihat seperti ini:
Perlu dicatat bahwa Anda juga dapat menggunakan variabel yang dihasilkan:
Tapi itu kurang penting daripada sebelum ada defaultdicts.
sumber
Kasus penggunaan lain yang menurut saya tidak disebutkan di atas. Kadang-kadang Anda menyimpan dict cache objek dengan id mereka di mana instance utama ada di cache dan Anda ingin mengatur cache ketika hilang.
Itu berguna ketika Anda selalu ingin menyimpan satu instance per id yang berbeda tidak peduli bagaimana Anda mendapatkan obj setiap kali. Misalnya ketika atribut objek diperbarui dalam memori dan penyimpanan ke penyimpanan ditangguhkan.
sumber
Satu use case yang sangat penting yang saya temukan:
dict.setdefault()
sangat bagus untuk kode multi-threaded ketika Anda hanya ingin satu objek kanonik (yang bertentangan dengan beberapa objek yang kebetulan sama).Misalnya,
(Int)Flag
Enum in Python 3.6.0 memiliki bug : jika beberapa utas bersaing untuk anggota komposit(Int)Flag
, mungkin ada lebih dari satu:Solusinya adalah digunakan
setdefault()
sebagai langkah terakhir untuk menyelamatkan anggota komposit yang dihitung - jika yang lain telah disimpan maka itu digunakan sebagai pengganti yang baru, menjamin anggota Enum yang unik.sumber
[Sunting] Sangat salah!Setdefault akan selalu memicu long_computation, Python bersemangat.
Memperluas jawaban Tuttle. Bagi saya kasus penggunaan terbaik adalah mekanisme cache. Dari pada:
yang menghabiskan 3 baris dan 2 atau 3 pencarian,
saya akan dengan senang hati menulis:sumber
long_computation(x)
hanya disebut jikax not in memo
. Padahal di yang kedua,long_computation(x)
selalu disebut. Hanya tugas bersyarat, kode setara dengansetdefault
akan terlihat seperti:v = long_computation(x)
/if x not in memo:
/memo[x] = v
.Saya suka jawaban yang diberikan di sini:
http://stupidpythonideas.blogspot.com/2013/08/defaultdict-vs-setdefault.html
Singkatnya, keputusan (dalam aplikasi non-kinerja-kritis) harus dibuat berdasarkan bagaimana Anda ingin menangani pencarian kunci kosong di hilir ( yaitu
KeyError
versus nilai default).sumber
Perbedaan use case
setdefault()
adalah ketika Anda tidak ingin menimpa nilai dari kunci yang telah ditetapkan.defaultdict
menimpa, sementarasetdefault()
tidak. Untuk kamus tersarang, lebih sering Anda ingin menetapkan default hanya jika kunci belum disetel, karena Anda tidak ingin menghapus sub kamus saat ini. Ini saat Anda menggunakansetdefault()
.Contoh dengan
defaultdict
:setdefault
tidak menimpa:sumber