Soal 1Kelompok mana yang isinya hanya tipe mutable?
Tipe Mutable dan Immutable
Pahami perbedaan tipe mutable dan immutable di Python serta jebakan referensi bersama yang sering memicu bug.
Kenapa kamu perlu mempelajari ini
Artikel ini bukan untuk pemula total, tapi topik ini tidak bisa dilewatkan jika kamu ingin memahami programming secara mendalam. Cerita klasik: pemula kena bug mutability dan menghabiskan berjam-jam untuk debug.
Di Python, kamu mungkin mengira y = x hanya menghubungkan dua variabel dengan tanda sama dengan, lalu menemukan bahwa mengedit salah satunya juga menimpa yang lain. Itulah mutability.
Bab ini menjernihkan perbedaan antara "mutable" (bisa diubah) dan "immutable" (tidak bisa diubah), dan menunjukkan cara menyalin dengan aman.
Tipe yang memungkinkanmu menulis ulang variabelnya sendiri (lewat append, assignment elemen, update, dan sejenisnya) disebut mutable; yang tidak bisa disebut immutable.
list / dict / set adalah mutable, dan sisanya (int / float / str / bool / tuple) adalah immutable.
Tipe immutable — mengubah salah satu tidak memengaruhi yang lain
Dengan tipe immutable (tipe yang tidak bisa diubah), setelah kamu mengoper nilainya lewat y = x, mengubah x setelahnya tidak berdampak pada y.
Misalnya, setelah x += 1, x jadi 11, tapi y tetap pada nilai semula 10.
# int bersifat immutable
x = 10
y = x
x += 1
print(x) # 11
print(y) # 10 <- tidak berubah
# str juga immutable
x = "hello"
y = x
x = x + " world"
print(x) # hello world
print(y) # hello
# tuple juga immutable
x = ("a", "b")
y = x
x = ("c", "d")
print(x) # ('c', 'd')
print(y) # ('a', 'b')
Variabel Python adalah "label nama yang menempel di kotak"
Sebuah variabel Python tidak menyimpan nilainya sendiri — ia lebih seperti label nama yang menunjuk ke data (sebuah kotak) di memori. Saat kamu menulis y = x, Python tidak membuat kotak baru; ia hanya menempelkan label nama lain (y) ke kotak yang sama yang ditunjuk x.
- Tipe immutable: rebinding seperti x = 11 hanya memindahkan label nama x ke kotak yang berbeda. y masih menunjuk ke kotak semula, jadi nilainya tetap independen.
- Tipe mutable: operasi in-place seperti x.append(...) mengubah kotak bersama itu sendiri, jadi perubahannya terlihat juga lewat y.
Inilah garis yang memisahkan immutable dari mutable.
Tipe mutable — dengan y = x, mengubah satu berarti mengubah yang lain
Sebaliknya, dengan tipe mutable (list / dict / set), menulis y = x membuat y dan x menunjuk ke kotak yang sama.
Jika kemudian kamu melakukan sesuatu yang menulis ulang isinya, misalnya x.append(...), perubahannya juga terlihat dari y.
y = x tidak membuat salinan terpisah — kedua nama menunjuk ke tempat yang sama.
Operasi yang menulis ulang isinya seperti append mengubah kotak bersama yang ditunjuk oleh kedua nama, sehingga perubahannya juga terlihat dari y.
# list bersifat mutable
x = ["a", "b"]
y = x # hanya menambahkan label y pada list yang sama
x.append("c") # menulis ulang isinya secara langsung
print(x) # ['a', 'b', 'c']
print(y) # ['a', 'b', 'c'] <- y juga bertambah!
# remove juga berperilaku sama
x.remove("b")
print(y) # ['a', 'c'] <- hilang juga dari y
# dict dan set menunjukkan perilaku yang sama
d = {"k": 1}
e = d
e["new"] = 99
print(d) # {'k': 1, 'new': 99} <- d juga bertambah
Kenapa berbagi adalah perilaku default?
Kalau y = x menyalin seluruh isinya setiap kali, maka ketika, misalnya, x berisi jutaan record yang diambil dari database, memori dan waktu eksekusi akan membengkak cepat.
Makanya di Python, nama variabel bukan nilainya itu sendiri — melainkan label yang menunjuk ke lokasi di memori.
Kamu tidak bisa mengubah mekanisme ini, jadi kamu (yang menulis code) yang harus berhati-hati memakainya.
Gunakan copy() untuk mendapatkan versi yang independen
Ketika kamu ingin menjaga data aslinya dan membuat versi terpisah, pakai metode copy().
Menulis y = x.copy() menyalin isinya ke kotak baru lalu menyerahkannya ke y, sehingga perubahan pada x setelahnya tidak memengaruhi y.
Pada saat y = x.copy(), wilayah memori baru dialokasikan.
Setelah itu, menulis ulang isi x dengan x.append(...) atau sejenisnya tidak berdampak sama sekali pada y.
# list / dict / set semuanya punya .copy()
x = ["apple", "lemon"]
y = x.copy()
x.append("grape")
print(x) # ['apple', 'lemon', 'grape']
print(y) # ['apple', 'lemon'] <- tidak terpengaruh
# dict.copy() bekerja sama
d = {"a": 1, "b": 2}
e = d.copy()
d["c"] = 3
print(d) # {'a': 1, 'b': 2, 'c': 3}
print(e) # {'a': 1, 'b': 2} <- tidak terpengaruh
# set.copy() bekerja sama
s = {1, 2}
t = s.copy()
s.add(3)
print(s) # {1, 2, 3}
print(t) # {1, 2} <- tidak terpengaruh
# list punya beberapa cara lain untuk disalin
x = ["apple", "lemon"]
y1 = list(x) # lewat constructor juga menghasilkan list baru
y2 = x[:] # salin seluruhnya lewat slice (dari awal sampai akhir)
Hati-hati kalau list berisi list lain
copy() hanya membuat kotak luar yang baru. Nilai mutable yang ada di dalamnya (seperti list di dalam list) tetap dibagi bersama. Ini disebut shallow copy (salinan dangkal).
Hati-hati saat menangani data bersarang.
Di artikel ini kamu belajar perbedaan antara tipe mutable dan immutable dan bagaimana copy() memberimu versi yang independen.
Gagasan bahwa nama variabel bukan nilainya itu sendiri melainkan label yang menunjuk ke lokasi di memori juga berlaku di bahasa lain, bukan hanya Python. Kalau kamu bekerja dengan tipe mutable, selipkan copy().
Cek Pemahaman
Jawab setiap pertanyaan satu per satu.
Soal 2Berapa nilai b setelah menjalankan code berikut?
``
a = [1, 2, 3]
b = a
a.append(4)
Soal 3Kamu ingin menjaga isi list asli a dan mendapatkan versi independen b. Cara menulis yang paling tepat yang mana?