Satu klasifikasi object menjelaskan banyak perilaku Python sekaligus: mengapa dua variabel bisa berubah bersamaan, mengapa operasi string selalu menghasilkan teks baru, dan mengapa dictionary menolak list sebagai key. Klasifikasi tersebut adalah mutable (isinya bisa diubah setelah dibuat) versus immutable (isinya dikunci permanen sejak dibuat). Chapter penutup Section ini membedah klasifikasi tersebut beserta jebakan paling terkenal yang lahir darinya.
Apa itu Mutable dan Immutable #
Object immutable tidak bisa diubah isinya setelah dibuat — setiap “perubahan” sebenarnya membuat object baru lalu mengikatkan ulang nama variabel. Object mutable sebaliknya: isinya bisa dimodifikasi di tempat tanpa kehilangan identitasnya. Tipe bawaan Python terbagi sebagai berikut:
| Tipe | Kategori |
|---|---|
int, float, complex, bool | Immutable |
str | Immutable |
tuple | Immutable |
list | Mutable |
dict | Mutable |
set | Mutable |
Kita sudah merasakan immutability pada Chapter String: percobaan nama[0] = "B" gagal dengan TypeError. Angka juga immutable — int, float, dan bool tidak pernah berubah nilai; assignment baru hanya memindahkan nama ke object yang berbeda.
Immutable Object dan Rebinding #
Perilaku assignment pada nilai immutable sering menipu pemula. Lihat dua variabel berikut:
a = 5
b = a
a += 1
print("a =", a)
print("b =", b)Output yang Dihasilkan:
a = 6
b = 5Pada baris a += 1, interpreter Python membuat object int baru bernilai 6, lalu mengikatkan ulang nama a ke object tersebut. Object 5 yang lama tidak pernah diubah — nama b tetap tenang menunjuk ke sana. Karena seluruh tipe numerik dan str bersifat immutable, pola ini berlaku untuk semua operasi augmented assignment pada tipe-tipe tersebut.
Jebakan Shared Reference pada List #
Situasi berubah total pada object mutable seperti list. Ingat dari Chapter Memahami Object dan Reference: assignment b = a tidak menyalin object, hanya membaginya. Pada list, isi object yang sama kini bisa berubah — dan perubahan itu terlihat dari semua nama penunjuknya:
buah_a = ["apel", "jeruk"]
buah_b = buah_a
buah_a.append("mangga")
print("buah_a:", buah_a)
print("buah_b:", buah_b)Output yang Dihasilkan:
buah_a: ['apel', 'jeruk', 'mangga']
buah_b: ['apel', 'jeruk', 'mangga']Mari kita telaah baris-baris kode di atas:
- Baris 1 (
buah_a = ["apel", "jeruk"]): interpreter membuat satu objectlistberisi dua string, lalu namabuah_amenunjuk ke object tersebut. - Baris 2 (
buah_b = buah_a): namabuah_bdiikatkan ke object yang sama — tidak ada list baru yang dibuat. - Baris 3 (
buah_a.append("mangga")): methodappend()mengubah isi object list di tempat; karena yang diubah adalah satu object bersama, isi yang dilihatbuah_bpun ikut bertambah. - Baris 5-6 (
print(...)): kedua nama mencetak object yang sama sehingga keduanya memuat"mangga".
Jika kita memang butuh dua list yang berdiri sendiri, buat salinan eksplisit dengan method .copy():
buah_a = ["apel", "jeruk"]
buah_b = buah_a.copy()
buah_a.append("mangga")
print("buah_a:", buah_a)
print("buah_b:", buah_b)Output yang Dihasilkan:
buah_a: ['apel', 'jeruk', 'mangga']
buah_b: ['apel', 'jeruk']Method .copy() membuat object list baru berisi elemen yang sama, sehingga nama buah_b kini menunjuk ke list terpisah dan append() pada buah_a tidak lagi menjalar. Ragam cara menyalin beserta perbedaan shallow dan deep copy akan kita bahas pada Section Struktur Data Dasar.
Tuple yang Berisi List #
Tuple menambah satu kasus tepi yang sering muncul di wawancara kerja: tuple memang immutable, tetapi kekekalan itu hanya berlaku pada struktur tuple-nya — elemen-elemennya tetap menunjuk ke object masing-masing. Jika salah satu elemen adalah list yang mutable, isi list tersebut tetap bisa berubah dari dalam tuple:
data = (1, 2, [3, 4])
data[2].append(5)
print(data)Output yang Dihasilkan:
(1, 2, [3, 4, 5])Baris data[2].append(5) sah karena yang diubah adalah isi object list di posisi ketiga, bukan susunan tuple-nya. Bandingkan dengan upaya mengganti elemen tuple itu sendiri:
data = (1, 2, [3, 4])
data[0] = 9Output yang Dihasilkan:
TypeError: 'tuple' object does not support item assignmentInterpreter Python menolak data[0] = 9 karena operasi tersebut mencoba mengganti arah penunjuk elemen tuple — bagian yang memang dikunci. Konsekuensi lanjutannya: tuple yang berisi list tidak bisa dijadikan key dictionary, karena Python mensyaratkan key bersifat hashable (immutable sepenuhnya).
Mengapa Ini Penting #
Klasifikasi mutable/immutable akan terus muncul di sepanjang perjalanan kita belajar Python:
- Argumen default function: nilai default yang mutable (misalnya
def tambah(item, keranjang=[])) dibagikan ke seluruh pemanggilan — jebakan klasik yang akan kita buktikan pada Section Fungsi. - Efek samping function: list yang dikirim ke dalam function bisa berubah isinya dan menular ke pemanggil; nilai immutable tidak pernah menular.
- Key dictionary dan anggota set: hanya nilai hashable (umumnya immutable) yang boleh menjadi key dictionary atau anggota set — dibahas pada Section Struktur Data Dasar.
- Manajemen memori: object immutable yang sama bisa dibagikan aman ke banyak nama, membantu interpreter menghemat memori — bahasan lanjutan pada Section Memory dan Performance.
Dengan memegang dua pertanyaan sederhana — “apakah object ini mutable?” dan “berapa nama yang menunjuk ke object ini?” — kita sudah memiliki bekal untuk memprediksi perilaku program Python secara jitu.