Tuple yang kita pelajari pada Chapter Tuple adalah record yang sangat hemat, tetapi juga sangat diam: pesanan[1] tidak memberi petunjuk apa pun tentang isinya, dan pesanan[0] yang tertukar dengan pesanan[2] tetap sah secara tipe. namedtuple mempertahankan seluruh perilaku tuple — immutable, ringan, bisa di-unpack — sambil memberi setiap posisi sebuah nama. Kita akan mempelajari dua cara pembuatannya dan kapan record ringan ini lebih tepat daripada dataclass.
Record Bernama dengan collections.namedtuple #
Fungsi namedtuple() dari module collections adalah factory yang membuat class tuple baru. Interpreter Python membangun class tersebut sekali saat panggilan namedtuple() dieksekusi; setelah itu class bisa dipakai seperti class biasa.
from collections import namedtuple
Titik = namedtuple("Titik", ["x", "y"])
p = Titik(3, 7)
print(p.x, p.y) # akses bernama
print(p[0], p[1]) # akses berindeks, seperti tuple biasa
print(p) # repr yang informatif
x, y = p # unpacking
print(f"x={x}, y={y}")Output yang Dihasilkan:
3 7
3 7
Titik(x=3, y=7)
x=3, y=7Mari kita telaah baris-baris pentingnya:
- Baris 3 (
Titik = namedtuple("Titik", ["x", "y"])): membuat classTitikbaru dengan dua field bernamaxdany. Argumen pertama adalah nama tipe untuk representasi, argumen kedua daftar nama field. - Baris 5 (
p = Titik(3, 7)): konstruktor classTitikmenerima nilai sesuai urutan field, sama seperti tuple biasa. - Baris 7 (
p.x): akses bernama —p.xdanp[0]membaca nilai yang sama, jadi kode pembaca tidak lagi perlu menghafal posisi. - Baris 11 (
x, y = p): karenapadalah tuple, unpacking ke variabelxdanybekerja langsung tanpa konversi.
_fields, _replace, dan _asdict #
Tiga method bawaan namedtuple paling sering dipakai untuk bekerja dengan record immutable:
from collections import namedtuple
Pesanan = namedtuple("Pesanan", ["id_pesanan", "pelanggan", "status"])
order = Pesanan("ORD-001", "Budi", "baru")
print(order._fields)
print(order._asdict())
# _replace() mengembalikan objek BARU, tidak memutasi yang lama
order_dikirim = order._replace(status="dikirim")
print(order)
print(order_dikirim)
# namedtuple immutable: assignment ditolak
try:
order.status = "batal"
except AttributeError as e:
print("AttributeError:", e)Output yang Dihasilkan:
('id_pesanan', 'pelanggan', 'status')
{'id_pesanan': 'ORD-001', 'pelanggan': 'Budi', 'status': 'baru'}
Pesanan(id_pesanan='ORD-001', pelanggan='Budi', status='baru')
Pesanan(id_pesanan='ORD-001', pelanggan='Budi', status='dikirim')
AttributeError: can't set attribute_fields mengembalikan tuple nama field, _asdict() mengubah record menjadi dict, dan _replace() membangun objek baru dengan sebagian field diganti — satu-satunya cara “mengubah” data yang immutable. Penugasan langsung order.status = "batal" ditolak dengan AttributeError, perilaku standar objek immutable sebagaimana dibahas pada Chapter Mutable dan Immutable Objects.
Dua method pendamping yang juga patut dikenal: Pesanan._make(["ORD-002", "Siti", "baru"]) membangun record dari iterable apa pun, dan Pesanan._asdict() hasilnya siap diserahkan ke json.dumps() karena berupa dict biasa. Karena namedtuple tidak menyimpan __dict__ per instance, memori yang dibutuhkan object-nya juga sama murahnya dengan tuple biasa — alasan utama record jenis ini populer pada pipeline yang memproses jutaan baris data.
Sintaks Class dengan typing.NamedTuple #
Untuk record yang sedikit lebih besar, module typing menyediakan NamedTuple dengan sintaks class dan annotasi tipe — kakek-neneknya @dataclass:
from typing import NamedTuple
class Pelanggan(NamedTuple):
nama: str
email: str = "[email protected]"
def sapa(self) -> str:
return f"Halo, {self.nama}!"
siti = Pelanggan("Siti")
budi = Pelanggan("Budi", "[email protected]")
print(siti)
print(budi.email)
print(budi.sapa())
print(siti._fields)Output yang Dihasilkan:
Pelanggan(nama='Siti', email='[email protected]')
[email protected]
Halo, Budi!
('nama', 'email')Perhatikan bahwa class Pelanggan mendukung nilai default per field (email), method biasa (sapa), dan tetap menghasilkan tuple — siti._fields serta unpacking bekerja persis seperti versi collections.namedtuple. Annotasi tipe pada class body sekaligus berfungsi sebagai deklarasi field, konvensi yang sama dengan Chapter Dataclasses.
namedtuple atau dataclass #
Keduanya sama-sama memecahkan masalah boilerplate; pembedanya ada pada sifat dasar hasilnya:
| Aspek | namedtuple | @dataclass |
|---|---|---|
| Mutabilitas | Immutable, selalu | Mutable secara default |
| Memori per instance | Paling ringan (adalah tuple) | Lebih besar, punya __dict__ |
Akses indeks, unpacking, _replace | Ya | Tidak |
Method, default factory, frozen/slots/order | Terbatas | Lengkap |
| Cocok untuk | record kecil, kembalian multi-nilai fungsi | model data utama aplikasi |
Aturan praktisnya: jika data tidak pernah berubah setelah dibuat, ukurannya kecil, dan ingin bekerja dengan ekosistem tuple (unpacking, iterasi), pilih namedtuple. Jika data butuh mutasi, default factory, atau dibekukan dengan hash — fasilitas yang dibahas pada Chapter Dataclasses — dataclass memberi ruang lebih luas.