List dan Perubahan Objek
Dalam Python, list bersifat mutable, sehingga isinya dapat diubah setelah dibuat. Dampak suatu operasi bergantung pada apakah operasi itu mengubah objek yang sama atau mengikat ulang nama.
Ketika sebuah list di-assign ke variabel, variabel tersebut hanya menyimpan referensi ke objek list. Assignment tidak menyalin isi list, sehingga beberapa nama atau container dapat merujuk ke objek yang sama.
# Membuat list dan memberikan referensi
list1 = [0, 1, 2]
list2 = ['a', list1, True]
print(list2) # ['a', [0, 1, 2], True]
# Mengubah elemen dalam list1
list1[1] = [3, 4, 5]
print(list2) # ['a', [0, [3, 4, 5], 2], True]Perhatikan bagaimana perubahan pada list1 juga memengaruhi list2. list2 adalah list luar yang berbeda. Elemen list2[1] merujuk ke objek yang sama dengan list1.
Full Slice Membuat Shallow Copy
Full slice seperti data[:] membuat list luar baru, tetapi elemen di dalamnya tetap merujuk ke objek yang sama. Hasil ini disebut shallow copy. Mengganti elemen pada bagian luar tidak memengaruhi list asal, tetapi objek mutable yang tersimpan di dalamnya masih dipakai bersama.
# Operasi slice menciptakan list baru
list1 = [0, 1, 2]
list2 = list1[:] # Mengambil semua elemen dengan slice
print(id(list1)) # Contoh: 3104
print(id(list2)) # Contoh: 8864 (berbeda dari list1)
# Mengubah elemen di list2 tidak memengaruhi list1
list2[0] = 'x'
print(list1) # [0, 1, 2] (tidak berubah)
print(list2) # ['x', 1, 2]
# Elemen mutable bertingkat tetap dipakai bersama oleh shallow copy
nested1 = [[1], [2]]
nested2 = nested1[:]
nested2[0].append(3)
print(nested1) # [[1, 3], [2]]Identitas Tipe dan Nilai Objek
Setiap objek Python memiliki tiga karakteristik: identitas, tipe, dan nilai.
Identitas Objek
Dua referensi memiliki identitas yang sama jika keduanya menunjuk ke objek yang sama. id() mengembalikan integer yang unik di antara objek-objek yang hidup bersamaan, sedangkan is membandingkan identitas secara langsung. Bahasa Python tidak menjamin bahwa integer tersebut merupakan alamat memori fisik.
a = 300
print(a) # 300
print(type(a)) # <class 'int'>
print(id(a)) # Contoh: 10120
b = a # b mereferensi objek yang sama dengan a
print(id(b)) # Contoh: 10120 (sama dengan a)
a = a + 1 # Membuat objek baru
print(id(a)) # Contoh: 10492 (berbeda dari sebelumnya)Membandingkan Identitas dan Nilai
Gunakan is untuk memeriksa apakah dua nama merujuk pada objek yang sama, terutama pada kondisi seperti value is None. Gunakan == untuk membandingkan nilai objek. Interpreter dapat memakai kembali objek tertentu atau menghitung ekspresi konstanta lebih awal. Akibatnya, dua nilai immutable kadang memiliki identitas yang sama. Jangan jadikan perilaku internal tersebut sebagai dasar logika program.
a = [1, 2]
b = a
c = [1, 2]
print(a is b) # True: objek yang sama
print(a == b) # True: nilai yang sama
print(a is c) # False: objek berbeda
print(a == c) # True: nilainya setaraPerubahan Isi Objek dan Pengikatan Ulang Nama
Python membagi objeknya menurut satu pertanyaan, yaitu apakah isinya bisa berubah setelah objek itu ada. Objek immutable seperti int, str, atau tuple menyimpan nilai yang sama sepanjang umurnya, sehingga operasi yang terlihat mengubah isi sebenarnya membuat objek baru. Objek mutable seperti list, dict, atau set menyimpan isi yang bisa berubah tanpa mengganti objeknya.
Dua nama yang menunjuk ke satu objek mutable sama-sama melihat perubahan isi itu, karena setiap nama melihat perubahan yang sama. Pengikatan ulang nama bekerja sebaliknya, sebab nama itu langsung menunjuk objek lain dan objek sebelumnya tetap seperti semula.
Objek Immutable
Objek immutable tidak dapat diubah setelah dibuat. Operasi yang tampak mengubah nilai objek sebenarnya membuat objek baru dan mengikat nama variabel ke objek tersebut.
# Integer bersifat immutable
a = 300
print(id(a)) # Contoh: 10120
a = a + 1 # Membuat objek baru
print(id(a)) # Contoh: 10492 (berbeda)
# String juga bersifat immutable
str_var = 'hello'
print(id(str_var)) # Contoh: 75568
# Mencoba mengubah string akan menghasilkan error
# str_var[1] = 'a' # TypeErrorTipe immutable dalam Python meliputi:
bool(boolean)int(integer)floatcomplex(bilangan kompleks)str(string)tuple(tuple)
Urutan referensi dalam tuple tidak dapat diubah, tetapi sebuah referensi tetap dapat menunjuk ke objek mutable seperti list.
Objek Mutable
Objek mutable dapat diubah tanpa membuat objek baru. Identitas objek tetap sama meskipun isinya berubah.
# List bersifat mutable
list_var = [0, 1, 2]
original = list_var
original_id = id(original)
# Mengubah elemen mempertahankan identitas list
list_var[0] = 9
print(id(list_var) == original_id) # True
# Reassignment menunjuk variabel ke objek baru
list_var = [0, 0, 0]
print(id(list_var) == original_id) # False
# Slice assignment mengubah list yang sama
current_id = id(list_var)
list_var[:] = ['a', 'b', 'c']
print(id(list_var) == current_id) # TrueTipe mutable dalam Python meliputi:
list(list)dict(dictionary)set(set)
Reassignment dan Mutation
Reassignment mengikat sebuah nama ke objek lain. Mutation mengubah isi objek yang sama, sehingga perubahannya dapat diakses melalui semua nama yang masih merujuk ke objek tersebut.
list1 = [0, 1, 2]
list2 = list1 # Kedua variabel mereferensi objek yang sama
print(id(list1)) # Contoh: 700
print(id(list2)) # Contoh: 700 (sama)
# Perubahan isi memengaruhi kedua variabel
list1[1] = 'x'
print(list1) # [0, 'x', 2]
print(list2) # [0, 'x', 2] (ikut berubah)
# Reassignment membuat referensi baru
list1 = [1, 2, 3]
print(list1) # [1, 2, 3]
print(list2) # [0, 'x', 2] (tidak berubah)Mutability menentukan apakah suatu operasi dapat mengubah objek yang sudah ada. Objek immutable mengurangi risiko perubahan pada state yang dipakai bersama, tetapi tidak otomatis membuat program thread-safe. Objek mutable, operasi majemuk, dan resource eksternal tetap memerlukan sinkronisasi yang dirancang dengan jelas.