Dict Lanjutan di Python
Kuasai get(), keys/values/items, dan dict bersarang untuk menangani data ala JSON tanpa takut KeyError.
Analogi singkat: kartu nama bertumpuk
Kalau dict dasar itu seperti satu kartu nama (nama jadi kunci, nomor jadi nilai), dict lanjutan itu seperti setumpuk kartu nama yang saling merujuk: kartu perusahaan berisi kartu kontak, kartu kontak berisi kartu alamat. Kamu harus bisa menyelam ke dalamnya dengan aman, tanpa program meledak karena satu kunci hilang.
get(): akses aman tanpa KeyError
siswa = {"nama": "Rina", "nilai": 85}
# akses langsung: error kalau kunci tidak ada
# print(siswa["kelas"]) # KeyError!
# get(): kembalikan None (atau default) kalau kunci hilang
print(siswa.get("kelas")) # None
print(siswa.get("kelas", "belum ada")) # belum ada
# pola praktis: hitung kemunculan tanpa if
kata = {}
for w in ["apel", "mangga", "apel", "apel"]:
kata[w] = kata.get(w, 0) + 1
print(kata) # {'apel': 3, 'mangga': 1}keys(), values(), items()
stok = {"kopi": 20, "teh": 35, "roti": 12}
for kunci in stok.keys():
print("kunci:", kunci)
for nilai in stok.values():
print("nilai:", nilai)
# items() paling sering dipakai: kunci DAN nilai sekaligus
for nama, jumlah in stok.items():
print(nama, "tersisa", jumlah)Catatan teknis:
keys(),values(),items()mengembalikan view yang mengikuti perubahan dict. Kalau butuh snapshot beku, bungkus denganlist(...).
Dict bersarang: data ala JSON
API dan file JSON hampir selalu berbentuk dict di dalam dict. Akses bertingkat dengan get berantai supaya aman:
pengguna = {
"nama": "Dedi",
"kontak": {
"email": "[email protected]",
"telepon": "08123456789",
},
"pesanan": [
{"barang": "kopi", "qty": 2},
{"barang": "roti", "qty": 1},
],
}
# akses bertingkat
print(pengguna["kontak"]["email"]) # [email protected]
# versi aman: berantai dengan get
kota = pengguna.get("alamat", {}).get("kota", "tidak diketahui")
print(kota) # tidak diketahui
# loop list of dict di dalamnya
for p in pengguna["pesanan"]:
print(p["barang"], "x", p["qty"])Contoh 1: agregasi penjualan per kategori
transaksi = [
{"kategori": "minuman", "nominal": 15000},
{"kategori": "makanan", "nominal": 12000},
{"kategori": "minuman", "nominal": 8000},
{"kategori": "makanan", "nominal": 20000},
]
rekap = {}
for t in transaksi:
k = t["kategori"]
rekap[k] = rekap.get(k, 0) + t["nominal"]
for kategori, total in rekap.items():
print(kategori, ": Rp", total)
# minuman : Rp 23000
# makanan : Rp 32000Ini pola paling umum di analisis data: kelompokkan berdasarkan satu kunci, jumlahkan nilainya.
Contoh 2: bangun struktur nested dari data datar
# data datar dari CSV -> ubah jadi nested per kota
baris = [
("Jakarta", "Rina", 25),
("Bandung", "Budi", 30),
("Jakarta", "Sari", 22),
]
per_kota = {}
for kota, nama, umur in baris:
per_kota.setdefault(kota, []).append({"nama": nama, "umur": umur})
print(per_kota["Jakarta"])
# [{'nama': 'Rina', 'umur': 25}, {'nama': 'Sari', 'umur': 22}]Catatan teknis:
setdefault(kunci, default)mengembalikan nilai yang ada, atau menyisipkan default lalu mengembalikannya. Pasangan serasigetuntuk pola akumulasi.
Kesalahan umum
SALAH: asumsi kunci selalu ada
print(data["email"]) # KeyError kalau baris datanya tidak punya emailBENAR: get dengan default yang masuk akal
print(data.get("email", ""))SALAH: mengubah ukuran dict saat iterasi
for k in stok:
if stok[k] == 0:
del stok[k] # RuntimeError: dictionary changed size during iterationBENAR: iterasi atas salinan daftar kunci
for k in list(stok.keys()):
if stok[k] == 0:
del stok[k]Tantangan
Rekap Nilai per Kelas
Diberi list dict berisi nama, kelas, dan nilai. Bangun dict rekap berisi total nilai per kelas memakai get(), lalu cetak tiap kelas dan totalnya.