Kapan menggunakan kamus vs tupel dengan Python

31

Contoh spesifik dalam pikiran adalah daftar nama file dan ukurannya. Saya tidak dapat memutuskan apakah setiap item dalam daftar harus dalam bentuk {"filename": "blabla", "size": 123}, atau adil ("blabla", 123). Kamus tampaknya lebih logis bagi saya karena untuk mengakses ukuran, misalnya, file["size"]lebih jelas daripada file[1]... tapi saya tidak benar-benar tahu pasti. Pikiran?

clb
sumber
Sebagai tambahan, pertimbangkan tuple membongkar , jika Anda khawatir tentang keterbacaan tuple - fname, file_size = file, di mana data tuple di atas Anda, akan menghapus file[1]dan menggantinya dengan file_size. Tentu saja ini bergantung pada dokumentasi yang baik.
nlsdfnbch
2
Tergantung struktur data apa yang Anda bangun, dan bagaimana Anda akan mengaksesnya? (berdasarkan nama file? dengan indeks? keduanya?) Apakah itu hanya variabel variabel / struktur data, atau apakah Anda akan menambahkan item (/ atribut) lain serta ukuran? Apakah struktur perlu mengingat pesanan; Anda ingin mengurutkan daftar ukuran, atau mengaksesnya dengan posisi (mis. "top-n file terbesar / terkecil")? Bergantung pada itu, jawaban 'terbaik' bisa dict, OrderedDict, namedtuple, daftar lama polos, atau kelas kustom Anda sendiri. Perlu lebih banyak konteks dari Anda.
smci

Jawaban:

78

Saya akan menggunakan namedtuple:

from collections import namedtuple
Filesize = namedtuple('Filesize', 'filename size')
file = Filesize(filename="blabla", size=123)

Sekarang Anda dapat menggunakan file.sizedan file.filenamedalam program Anda, yang merupakan bentuk IMHO paling mudah dibaca. Note namedtuplemenciptakan objek yang tidak dapat diubah seperti tuple, dan mereka lebih ringan daripada kamus, seperti dijelaskan di sini .

Doc Brown
sumber
1
Terima kasih, ide bagus, belum pernah mendengar tentang mereka sebelum hari ini (saya cukup tahu tentang Python). Pertanyaan: apa yang terjadi jika seseorang di tempat lain dalam kode juga mendefinisikan "kelas" yang sama, mungkin sedikit berbeda. misalnya, dalam beberapa file sumber lain, rekan kerja Bob memilikiFilesize = namedtuple('Filesize', 'filepath kilobytes')
user949300
Anda juga dapat menggunakan attrsmodul yang sangat bagus (dapat menemukannya melalui pipatau hanya mencarinya), yang memungkinkan Anda memiliki kemudahan sintaksis yang sangat mirip dengan nama tuple, tetapi dapat memberi Anda mutabilitas (tetapi juga dapat dibuat tidak berubah). Perbedaan fungsional utama adalah bahwa attrskelas buatan tidak sebanding dengan tupel biasa, seperti namedtupleyang dilakukan s.
mtraceur
3
@DocBrown Python tidak memiliki konsep deklarasi. class,, defdan =semua hanya menimpa penggunaan sebelumnya. repl.it
Challenger5
@ Challenger5: Anda benar, kesalahan saya, jadi jawaban yang benar adalah: jumlah definisi terbaru, tidak ada kesalahan dari runtime Python, tetapi perilaku masih sama seperti variabel lainnya.
Doc Brown
8
Perhatikan bahwa namedtuplepada dasarnya adalah deklarasi tangan pendek untuk tipe baru dengan atribut yang tidak dapat diubah. Ini berarti jawabannya secara efektif, "Bukan a tupleatau a dict, tetapi sebuah object." +1
jpmc26
18

{"nama file": "blabla", "size": 123}, atau hanya ("blabla", 123)

Ini adalah pertanyaan lama apakah akan menyandikan format / skema Anda di-band atau di luar-band.

Anda menukar sebagian memori untuk mendapatkan keterbacaan dan portabilitas yang berasal dari mengekspresikan format data langsung dalam data. Jika Anda tidak melakukan ini, pengetahuan bahwa bidang pertama adalah nama file dan yang kedua adalah ukuran harus disimpan di tempat lain. Itu menghemat memori tetapi biaya keterbacaan dan portabilitas. Mana yang akan membuat perusahaan Anda mengeluarkan uang lebih banyak?

Adapun masalah abadi, ingat kekekalan tidak berarti tidak berguna dalam menghadapi perubahan. Itu berarti kita perlu mengambil lebih banyak memori, membuat perubahan dalam salinan, dan menggunakan salinan baru. Itu tidak gratis tetapi sering kali bukan pemecah kesepakatan. Kami menggunakan string abadi untuk mengubah hal-hal sepanjang waktu.

Pertimbangan lain adalah ekstensibilitas. Ketika Anda menyimpan data hanya secara posisi, tanpa menyandikan informasi format, maka Anda hanya dikutuk untuk pewarisan tunggal, yang sebenarnya hanyalah praktik menggabungkan bidang tambahan setelah bidang yang ditetapkan. Saya dapat menetapkan bidang ke-3 sebagai tanggal pembuatan dan masih kompatibel dengan format Anda karena saya mendefinisikan pertama dan kedua dengan cara yang sama.

Namun, yang tidak bisa saya lakukan adalah menyatukan dua format yang didefinisikan secara independen yang memiliki beberapa bidang yang tumpang tindih, beberapa tidak, menyimpannya dalam satu format, dan membuatnya berguna untuk hal-hal yang hanya tahu tentang satu atau format lainnya.

Untuk melakukan itu saya harus menyandikan info format dari awal. Saya perlu mengatakan "bidang ini adalah nama file". Melakukan hal itu memungkinkan pewarisan berganda.

Anda mungkin terbiasa pewarisan hanya diekspresikan dalam konteks objek tetapi ide yang sama bekerja untuk format data karena, well, objek disimpan dalam format data. Persis masalah yang sama.

Jadi gunakan mana pun yang menurut Anda paling mungkin Anda butuhkan. Saya meraih fleksibilitas kecuali saya bisa menunjukkan alasan yang baik untuk tidak melakukannya.

candied_orange
sumber
3
Sejujurnya, saya ragu siapa pun yang tidak yakin antara menggunakan format in-band atau out-of-band memiliki persyaratan kinerja yang sangat ketat sehingga mereka perlu perlu menggunakan format out-of-band
Alexander - Reinstate Monica
2
@Alexander sangat benar. Saya lebih suka mengajar orang-orang tentang hal itu sehingga mereka mengerti apa yang mereka lihat ketika dihadapkan dengan solusi out-of-band. Format biner sering melakukan ini karena alasan kebingungan. Tidak semua orang ingin menjadi portabel. Adapun alasan kinerja, jika itu benar-benar penting pertimbangkan kompresi sebelum beralih ke out-of-band.
candied_orange
Ingat bahwa OP menggunakan Python, jadi mereka mungkin tidak terlalu peduli dengan kinerja. Sebagian besar kode tingkat tinggi harus ditulis dengan keterbacaan terlebih dahulu; optimasi prematur adalah akar dari semua kejahatan.
Dagrooms
@ Kamar tidak membenci Python. Berkinerja baik dalam banyak kasus. Tetapi sebaliknya saya setuju dengan semua yang Anda katakan. Maksud saya adalah untuk mengatakan "Inilah sebabnya orang melakukan itu. Inilah mengapa Anda mungkin tidak peduli".
candied_orange
@CandiedOrange Saya tidak membenci bahasa, saya menggunakannya dalam pekerjaan sehari-hari saya. Saya tidak suka cara orang menggunakannya.
Dagrooms
7

Saya akan menggunakan kelas dengan dua properti. file.sizelebih baik daripada salah satu file[1]atau file["size"].

Sederhana lebih baik daripada kompleks.

JacquesB
sumber
Jika seseorang bertanya-tanya: Untuk menghasilkan JSON, keduanya bekerja sama baiknya: file = Filesize(filename='stuff.txt', size=222)dan filetup = ("stuff.txt", 222)keduanya menghasilkan JSON yang sama: json.dumps(file)dan json.dumps(filetup)menghasilkan:'["stuff.txt", 222]'
Juha Untinen
5

Apakah nama filenya unik? Jika demikian, Anda dapat menghapus daftar seluruhnya dan hanya menggunakan kamus murni untuk semua file. mis. (situs web hipotetis)

{ 
  "/index.html" : 5467,
  "/about.html" : 3425,
  "/css/main.css" : 9876
}

dll ...

Sekarang, Anda tidak mendapatkan "nama" dan "ukuran", Anda hanya menggunakan kunci dan nilai, tetapi seringkali ini lebih alami. YMMV.

Jika Anda benar - benar menginginkan "ukuran" untuk kejelasan, atau Anda membutuhkan lebih dari satu nilai untuk file, maka:

{ 
   "/index.html" : { "size": 5467, "mime_type" : "foo" },
   "/about.html" : { "size": 3425, "mime_type" : "foo" }
   "/css/main.css" : { "size": 9876, "mime_type" : "bar" }
}
pengguna949300
sumber
0

Dalam python, kamus adalah objek yang bisa berubah. Di sisi lain, tuple adalah objek abadi.

jika Anda perlu mengubah kunci kamus, pasangan nilai sering atau setiap kali. saya sarankan kamus untuk digunakan.

jika Anda memiliki data statis / tetap, saya sarankan tuple untuk digunakan.

# dictionary define.
a = {}
a['test'] = 'first value'

# tuple define.
b = ()
b = b+(1,)

# here, we can change dictionary value for key 'test'
a['test'] = 'second'

Tapi, tidak bisa mengubah data tuple menggunakan operator penugasan.

Memperdalam Patel
sumber