Sampai titik ini kita memperlakukan string sebagai teks yang “sudah jadi”. Kenyataannya, komputer hanya menyimpan angka, dan teks hanyalah kesepakatan penerjemahan: setiap karakter dipetakan ke sebuah nomor, lalu nomor tersebut disimpan sebagai bytes. Python 3 dirancang di atas standar Unicode, dan memisahkan dua tipe data secara tegas: str untuk teks yang sudah diterjemahkan, bytes untuk data mentah. Memahami batas antara keduanya adalah kunci menghindari satu keluarga error yang paling sering menyebutkan namanya di layar pembaca: UnicodeDecodeError.
Karakter adalah Angka: ord() dan chr() #
Setiap karakter Unicode memiliki nomor resmi yang disebut code point. Fungsi bawaan ord() melaporkan nomor tersebut dari sebuah karakter, dan chr() melakukan arah sebaliknya:
print(ord("A"))
print(ord("é"))
print(chr(233))
print(chr(0x6F22))Output yang Dihasilkan:
65
233
é
漢Huruf A ternyata adalah angka 65, sedangkan huruf é adalah 233. Fungsi chr() menerima angka dalam bentuk apa pun yang sah di Python — desimal seperti 233 maupun heksadesimal seperti 0x6F22 yang menghasilkan karakter CJK 漢. String "A" di Python dengan demikian adalah urutan code point [65], bukan sekadar “huruf di layar”.
str vs bytes #
Python 3 memisahkan teks dan data biner dengan tipe yang berbeda:
str— teks; setiap elemen adalah satu karakter (satu code point Unicode).bytes— urutan byte mentah; literal-nya ditulis dengan prefixb, misalnyab"Budi".
Konversi dari str ke bytes dilakukan method encode(), dan sebaliknya dengan decode(). Keduanya membutuhkan nama encoding — kesepakatan bagaimana code point diterjemahkan menjadi byte. Encoding default Python adalah UTF-8, standar yang mampu merepresentasikan seluruh karakter Unicode:
teks = "Budi"
data = teks.encode("utf-8")
print(data)
print(type(data))
print(len(data))Output yang Dihasilkan:
b'Budi'
<class 'bytes'>
4Method encode() menghasilkan object bytes yang ditampilkan dengan prefix b. Perhatikan baris terakhir: untuk teks murni ASCII seperti "Budi", UTF-8 memakai satu byte per karakter sehingga panjang data 4 byte sama dengan jumlah karakternya. Karakter di luar ASCII seperti é membutuhkan lebih dari satu byte:
teks = "café"
data = teks.encode("utf-8")
print(data)
print(len(teks))
print(len(data))
pulih = data.decode("utf-8")
print(pulih)Output yang Dihasilkan:
b'caf\xc3\xa9'
4
5
caféMari kita bedah hasil di atas:
- Baris 4 (
b'caf\xc3\xa9'): hurufédisimpan sebagai dua byte, ditampilkan Python dalam heksadesimal\xc3\xa9; tiga karakter pertama yang ber-ASCII tetap terbacacaf. - Baris 5-6 (
len(teks)vslen(data)): stringcafémemiliki4karakter, sedangkan versi bytes-nya memiliki5byte — panjang byte dan jumlah karakter adalah dua hal berbeda begitu teks keluar dari wilayah ASCII. - Baris 8 (
decode("utf-8")): proses kebalikan mengembalikan tekscaféyang identik dengan aslinya.
UnicodeDecodeError #
Masalah muncul ketika bytes didekode dengan asumsi encoding yang salah atau ketika data biner bukan teks sama sekali. Method decode() secara default memakai mode strict yang memicu UnicodeDecodeError begitu menemui byte yang tidak sah:
>>> b"\xff".decode("utf-8")
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xff in position 0: invalid start byteByte 0xff bukan awal karakter UTF-8 yang sah, sehingga interpreter Python menolak menebak. Dua penyebab paling umum dari error ini di dunia nyata: berkas teks dibuka sebagai bytes lalu didekode dengan encoding yang keliru (misalnya berkas Windows-1252 didekode sebagai UTF-8), atau data biner seperti gambar diperlakukan sebagai teks. Solusinya bukan menangkap error lalu berpura-pura tidak terjadi, melainkan mengetahui encoding asli data tersebut dan menyebutkannya secara eksplisit.
Selalu Sebutkan encoding saat Membaca Berkas #
Fungsi open() membaca berkas sebagai str, dan tanpa ditunjuk, encoding yang dipakai mengikuti pengaturan sistem operasi — kode yang berjalan mulus di satu mesin bisa memicu UnicodeDecodeError di mesin lain. Praktik yang benar adalah selalu menyebutkan encoding="utf-8" secara eksplisit:
with open("daftar.txt", "w", encoding="utf-8") as berkas:
berkas.write("Budi Santoso\nSiti Nurhaliza\nJoko Anwar")
with open("daftar.txt", encoding="utf-8") as berkas:
isi = berkas.read()
print(isi)Output yang Dihasilkan:
Budi Santoso
Siti Nurhaliza
Joko AnwarPernyataan with open(...) as berkas membuka berkas dan menjamin berkas tertutup otomatis setelah bloknya selesai; mekanisme lengkap pembacaan dan penulisan berkas dibahas tuntas pada section File Handling. Dengan encoding="utf-8" pada kedua pemanggilan, program kita berperilaku sama di komputer mana pun — inilah alasan menulis encoding secara eksplisit dianggap wajib, bukan sekadar gaya.
Model mental yang perlu kita bawa: str adalah teks, bytes adalah angka mentah, dan UTF-8 adalah jembatan resmi di antara keduanya. Bab terakhir section ini memperkenalkan perangkat yang bekerja di atas teks berformat rumit: regular expressions.