Tipe Data #
Setiap nilai di Python memiliki tipe — dan tipe menentukan operasi apa yang bisa dilakukan terhadap nilai tersebut. Python bersifat strongly typed: tidak ada konversi implisit antara tipe yang tidak kompatibel. Kamu tidak bisa langsung menambahkan angka dengan string seperti di JavaScript. Tapi Python juga dynamically typed: tipe ditentukan saat runtime, bukan saat kompilasi. Memahami tipe data dengan baik — termasuk mana yang mutable dan mana yang immutable, bagaimana konversi bekerja, dan jebakan-jebakan yang tidak intuitif — adalah fondasi penting sebelum menulis kode Python yang lebih kompleks.
Peta Tipe Data Python #
Tipe Data Python
│
├── Skalar (nilai tunggal)
│ ├── int → bilangan bulat: 42, -7, 0
│ ├── float → bilangan desimal: 3.14, -0.5, 1e10
│ ├── complex → bilangan kompleks: 3+4j
│ ├── bool → True / False
│ └── NoneType → None
│
└── Koleksi (kumpulan nilai)
├── Terurut & Mutable
│ └── list → [1, 2, 3]
├── Terurut & Immutable
│ ├── tuple → (1, 2, 3)
│ └── str → "hello"
├── Tidak Terurut & Mutable
│ ├── dict → {"key": "value"}
│ └── set → {1, 2, 3}
└── Tidak Terurut & Immutable
└── frozenset → frozenset({1, 2, 3})
int — Bilangan Bulat
#
Python int tidak memiliki batas ukuran — bisa menampung bilangan bulat sebesar yang mampu ditampung memori. Ini berbeda dari bahasa seperti Java yang punya int (32-bit) dan long (64-bit).
# Literal integer dalam berbagai basis
desimal = 255 # basis 10 (default)
biner = 0b11111111 # basis 2 → 255
oktal = 0o377 # basis 8 → 255
heksadesimal = 0xFF # basis 16 → 255
print(desimal, biner, oktal, heksadesimal)
# → 255 255 255 255
# Python mendukung integer tak terbatas
faktorial_100 = 1
for i in range(1, 101):
faktorial_100 *= i
print(faktorial_100) # → angka 158 digit, tidak overflow!
# Operasi pembagian — perhatikan perbedaannya
print(10 / 3) # → 3.3333... (selalu float, meski habis dibagi)
print(10 // 3) # → 3 (pembagian bulat, hasilnya int)
print(10 % 3) # → 1 (sisa bagi / modulo)
print(2 ** 10) # → 1024 (pemangkatan)
# Pemisah ribuan untuk keterbacaan
populasi = 270_000_000
anggaran = 1_500_000_000
print(populasi) # → 270000000
float — Bilangan Desimal
#
float di Python menggunakan representasi IEEE 754 double precision (64-bit). Ini memberikan presisi sekitar 15–17 digit desimal, tapi juga membawa konsekuensi yang sering mengejutkan pemula.
# Literal float
pi = 3.14159
avogadro = 6.022e23 # notasi ilmiah: 6.022 × 10²³
kecil = 1.5e-10 # 1.5 × 10⁻¹⁰
print(avogadro) # → 6.022e+23
print(kecil) # → 1.5e-10
Jebakan Presisi Float #
# ANTI-PATTERN: membandingkan float secara langsung
print(0.1 + 0.2) # → 0.30000000000000004 (bukan 0.3!)
print(0.1 + 0.2 == 0.3) # → False ← jebakan klasik!
# Mengapa? Karena 0.1 dan 0.2 tidak bisa direpresentasikan
# secara persis dalam biner (seperti 1/3 dalam desimal)
# BENAR: gunakan math.isclose() untuk perbandingan float
import math
print(math.isclose(0.1 + 0.2, 0.3)) # → True
print(math.isclose(0.1 + 0.2, 0.3, rel_tol=1e-9)) # → True
# Atau round() untuk membulatkan sebelum membandingkan
print(round(0.1 + 0.2, 10) == round(0.3, 10)) # → True
# ANTI-PATTERN: menggunakan float untuk kalkulasi uang/finansial
harga = 19.99
pajak = 0.11
total = harga * (1 + pajak)
print(total) # → 22.18890000000000... (tidak presisi untuk uang!)
# BENAR: gunakan modul decimal untuk kalkulasi finansial
from decimal import Decimal, ROUND_HALF_UP
harga = Decimal("19.99")
pajak = Decimal("0.11")
total = harga * (1 + pajak)
print(total) # → 22.1889
# Bulatkan ke 2 desimal
total_bulat = total.quantize(Decimal("0.01"), rounding=ROUND_HALF_UP)
print(total_bulat) # → 22.19
Jangan pernah gunakanfloatuntuk kalkulasi yang melibatkan uang, keuangan, atau nilai yang memerlukan presisi desimal eksak. Gunakan moduldecimaldari stdlib Python — dirancang khusus untuk kebutuhan ini.
str — String (Teks)
#
String di Python adalah urutan karakter Unicode yang immutable — sekali dibuat, nilainya tidak bisa diubah. Setiap operasi string menghasilkan string baru.
# Cara membuat string
s1 = 'tanda kutip tunggal'
s2 = "tanda kutip ganda"
s3 = """string
multi-baris
dengan triple-quote"""
s4 = '''ini juga
bisa multi-baris'''
# String raw — backslash tidak diinterpretasi sebagai escape
path_windows = r"C:\Users\Budi\Documents" # r = raw string
regex_pola = r"\d+\.\d+" # berguna untuk regex
print(path_windows) # → C:\Users\Budi\Documents
# String bytes — untuk data biner
data_biner = b"hello"
print(type(data_biner)) # → <class 'bytes'>
Operasi String Penting #
teks = "Selamat Datang di Python"
# Indexing dan slicing
print(teks[0]) # → S (indeks pertama)
print(teks[-1]) # → n (indeks terakhir)
print(teks[0:7]) # → Selamat
print(teks[8:]) # → Datang di Python
print(teks[:7]) # → Selamat
print(teks[::2]) # → SlmtDtn iPto (setiap 2 karakter)
print(teks[::-1]) # → nohtyP id gnataDtamlaleS (terbalik)
# Metode string yang sering dipakai
print(teks.upper()) # → SELAMAT DATANG DI PYTHON
print(teks.lower()) # → selamat datang di python
print(teks.split(" ")) # → ['Selamat', 'Datang', 'di', 'Python']
print(teks.replace("Python", "Dunia")) # → Selamat Datang di Dunia
print(" spasi ".strip()) # → spasi
print(teks.startswith("Sel")) # → True
print(teks.endswith("on")) # → True
print("Python" in teks) # → True
print(len(teks)) # → 24
Format String #
nama = "Budi"
skor = 92.5
peringkat = 3
# f-string (Python 3.6+) — cara yang direkomendasikan
print(f"Halo, {nama}!") # → Halo, Budi!
print(f"Skor: {skor:.1f}") # → Skor: 92.5
print(f"Skor: {skor:.0f}") # → Skor: 93 (dibulatkan)
print(f"Peringkat ke-{peringkat:02d}") # → Peringkat ke-03
print(f"Nilai: {skor!r}") # → Nilai: 92.5
print(f"{'kiri':<10}|{'tengah':^10}|{'kanan':>10}")
# → kiri | tengah | kanan
# ANTI-PATTERN: concatenation dalam loop — sangat lambat untuk string panjang
kata_list = ["Python", "adalah", "bahasa", "yang", "hebat"]
hasil = ""
for kata in kata_list:
hasil += kata + " " # membuat string baru setiap iterasi
# BENAR: gunakan join()
hasil = " ".join(kata_list)
print(hasil) # → Python adalah bahasa yang hebat
bool — Boolean
#
bool adalah subkelas dari int di Python. True sama dengan 1 dan False sama dengan 0 — ini memungkinkan beberapa trik ringkas tapi juga jadi sumber kebingungan.
print(True + True) # → 2
print(True * 5) # → 5
print(False + 1) # → 1
print(isinstance(True, int)) # → True (bool adalah subkelas int!)
# Nilai truthy dan falsy
# Semua nilai di bawah ini dianggap False saat digunakan dalam kondisi:
falsy_values = [
False, 0, 0.0, 0j, # angka nol
"", '', b"", # string kosong
[], (), {}, set(), # koleksi kosong
None, # None
]
# Semua nilai lain dianggap True
print(bool(42)) # → True
print(bool(-1)) # → True (negatif pun True!)
print(bool("")) # → False
print(bool("0")) # → True (string "0" bukan nol!)
print(bool([])) # → False
print(bool([0])) # → True (list dengan 1 elemen meski nol)
# Memanfaatkan truthy/falsy secara idiomatis
nama = ""
# ANTI-PATTERN: perbandingan eksplisit dengan string kosong
if nama == "":
print("nama kosong")
# BENAR: cukup evaluasi langsung
if not nama:
print("nama kosong")
# Contoh lain: cek list kosong
data = []
if not data:
print("tidak ada data")
None — Tidak Ada Nilai
#
None adalah satu-satunya nilai dari tipe NoneType. Digunakan untuk merepresentasikan ketiadaan nilai, mirip dengan null di bahasa lain.
# Penggunaan umum None
def cari_pengguna(user_id):
# mengembalikan None jika tidak ditemukan
if user_id not in database:
return None
return database[user_id]
hasil = cari_pengguna(999)
# ANTI-PATTERN: membandingkan None dengan ==
if hasil == None:
print("tidak ditemukan")
# BENAR: selalu gunakan 'is' atau 'is not' untuk None
if hasil is None:
print("tidak ditemukan")
if hasil is not None:
print(f"ditemukan: {hasil}")
# None sebagai default parameter (pola umum di Python)
def tambah_ke_list(nilai, target=None):
# ANTI-PATTERN: menggunakan list sebagai default langsung
# def tambah_ke_list(nilai, target=[]): ← BAHAYA! list default dishare antar pemanggilan
# BENAR: gunakan None sebagai sentinel, buat list baru di dalam fungsi
if target is None:
target = []
target.append(nilai)
return target
print(tambah_ke_list(1)) # → [1]
print(tambah_ke_list(2)) # → [2] (list baru, bukan [1, 2]!)
Tipe Koleksi #
list — Koleksi Terurut yang Bisa Diubah
#
# Membuat list
angka = [1, 2, 3, 4, 5]
campuran = [42, "hello", 3.14, True, None] # boleh tipe berbeda
bersarang = [[1, 2], [3, 4], [5, 6]] # list di dalam list
kosong = []
# Operasi dasar
angka.append(6) # tambah di akhir → [1,2,3,4,5,6]
angka.insert(0, 0) # tambah di indeks 0 → [0,1,2,3,4,5,6]
angka.pop() # hapus & kembalikan elemen terakhir → 6
angka.pop(0) # hapus & kembalikan elemen indeks 0 → 0
angka.remove(3) # hapus nilai 3 (kemunculan pertama)
angka.sort() # urutkan di tempat (in-place)
angka.reverse() # balik urutan di tempat
print(len(angka)) # → jumlah elemen
print(3 in angka) # → True/False
tuple — Koleksi Terurut yang Tidak Bisa Diubah
#
# Membuat tuple
koordinat = (10.5, -6.2)
rgb = (255, 128, 0)
satu_elemen = (42,) # koma wajib untuk tuple 1 elemen!
kosong = ()
# JEBAKAN: tuple 1 elemen tanpa koma
bukan_tuple = (42) # ini int biasa, bukan tuple
print(type(bukan_tuple)) # → <class 'int'>
print(type((42,))) # → <class 'tuple'>
# Tuple immutable — tidak bisa diubah
koordinat[0] = 99 # TypeError: 'tuple' object does not support item assignment
# Kapan gunakan tuple vs list?
# Tuple: data yang tidak seharusnya berubah (koordinat, RGB, record database)
# List: data yang akan dimodifikasi (keranjang belanja, antrian proses)
dict — Pasangan Kunci-Nilai
#
# Membuat dict
pengguna = {
"nama": "Budi Santoso",
"umur": 28,
"email": "[email protected]",
"aktif": True,
}
# Akses nilai
print(pengguna["nama"]) # → Budi Santoso
print(pengguna.get("telepon")) # → None (tidak error jika key tidak ada)
print(pengguna.get("telepon", "-")) # → - (nilai default)
# ANTI-PATTERN: akses langsung tanpa cek
telepon = pengguna["telepon"] # KeyError jika key tidak ada
# BENAR: gunakan .get() untuk key yang mungkin tidak ada
telepon = pengguna.get("telepon", "tidak tersedia")
# Operasi dict
pengguna["telepon"] = "081234567890" # tambah/update key
del pengguna["aktif"] # hapus key
print("email" in pengguna) # → True (cek keberadaan key)
# Iterasi
for key in pengguna:
print(key)
for key, value in pengguna.items():
print(f"{key}: {value}")
print(list(pengguna.keys())) # → ['nama', 'umur', 'email', 'telepon']
print(list(pengguna.values())) # → ['Budi Santoso', 28, '[email protected]', '...']
set — Koleksi Nilai Unik
#
# Membuat set
buah = {"apel", "jeruk", "mangga", "apel"} # duplikat otomatis dihapus
print(buah) # → {'apel', 'jeruk', 'mangga'} (urutan tidak dijamin)
# set kosong HARUS menggunakan set(), bukan {}
kosong = set() # ✓ set kosong
bukan_set = {} # ✗ ini dict kosong, bukan set!
# Operasi himpunan
a = {1, 2, 3, 4, 5}
b = {3, 4, 5, 6, 7}
print(a | b) # union (gabungan) → {1,2,3,4,5,6,7}
print(a & b) # intersection (irisan) → {3,4,5}
print(a - b) # difference (selisih) → {1,2}
print(a ^ b) # symmetric difference → {1,2,6,7}
# Penggunaan umum: hapus duplikat dari list
data = [1, 2, 2, 3, 3, 3, 4]
unik = list(set(data))
print(unik) # → [1, 2, 3, 4] (urutan tidak dijamin)
# Cek keanggotaan — O(1), jauh lebih cepat dari list
print(3 in a) # → True
Mutable vs Immutable #
Perbedaan ini krusial untuk dipahami — banyak bug tersembunyi berasal dari salah memahami mana yang mutable dan mana yang tidak.
Immutable (tidak bisa diubah): Mutable (bisa diubah):
───────────────────────────── ────────────────────────
int, float, complex list
str dict
bool set
tuple bytearray
frozenset
bytes
# Immutable: operasi menghasilkan objek BARU
s = "hello"
s_baru = s.upper() # s tidak berubah, s_baru adalah objek baru
print(s) # → hello
print(s_baru) # → HELLO
# Mutable: operasi mengubah objek YANG SAMA
lst = [1, 2, 3]
lst.append(4) # lst dimodifikasi langsung
print(lst) # → [1, 2, 3, 4]
# Konsekuensi penting: objek mutable tidak bisa dijadikan key dict
d = {}
d[(1, 2)] = "tuple sebagai key" # ✓ tuple immutable
d[[1, 2]] = "list sebagai key" # ✗ TypeError: unhashable type: 'list'
Konversi Tipe Data #
Python menyediakan fungsi bawaan untuk konversi eksplisit antar tipe. Penting untuk diingat: tidak semua konversi akan berhasil — beberapa bisa melempar exception.
# int() — konversi ke integer
print(int("42")) # → 42
print(int(3.99)) # → 3 (dipotong, bukan dibulatkan!)
print(int(True)) # → 1
print(int("0xFF", 16)) # → 255 (string hex ke int)
# Yang akan gagal:
# int("3.14") → ValueError: invalid literal for int()
# int("hello") → ValueError
# float() — konversi ke float
print(float("3.14")) # → 3.14
print(float(42)) # → 42.0
print(float("inf")) # → inf
# str() — konversi ke string (selalu berhasil)
print(str(42)) # → "42"
print(str(3.14)) # → "3.14"
print(str(True)) # → "True"
print(str(None)) # → "None"
print(str([1, 2, 3])) # → "[1, 2, 3]"
# bool() — konversi ke boolean
print(bool(0)) # → False
print(bool("")) # → False
print(bool([])) # → False
print(bool(42)) # → True
print(bool("false")) # → True (string non-kosong selalu True!)
# Konversi koleksi
print(list((1, 2, 3))) # tuple → list: [1, 2, 3]
print(tuple([1, 2, 3])) # list → tuple: (1, 2, 3)
print(set([1, 2, 2, 3])) # list → set: {1, 2, 3}
print(list("hello")) # str → list: ['h','e','l','l','o']
print("".join(['h','i'])) # list → str: "hi"
Konversi yang Aman dengan Penanganan Error #
def ke_int_aman(nilai, default=0):
"""Konversi ke int tanpa melempar exception."""
try:
return int(nilai)
except (ValueError, TypeError):
return default
print(ke_int_aman("42")) # → 42
print(ke_int_aman("abc")) # → 0 (default)
print(ke_int_aman("abc", -1)) # → -1 (custom default)
print(ke_int_aman(None)) # → 0
Mengecek Tipe Data #
x = 42
# type() — mengembalikan tipe persis
print(type(x)) # → <class 'int'>
print(type(x) == int) # → True
# isinstance() — cek tipe termasuk subkelas (lebih direkomendasikan)
print(isinstance(x, int)) # → True
print(isinstance(x, (int, float))) # → True (cek beberapa tipe sekaligus)
print(isinstance(True, int)) # → True (bool adalah subkelas int)
# ANTI-PATTERN: type() untuk cek tipe — tidak mengenali subkelas
print(type(True) == int) # → False (meski True adalah subkelas int)
# BENAR: isinstance() untuk cek tipe
print(isinstance(True, int)) # → True
Ringkasan #
inttidak terbatas ukurannya — tidak perlu khawatir overflow seperti di C/Java. Python otomatis mengelola memori untuk integer besar.- Jangan bandingkan float dengan
==— gunakanmath.isclose(). Representasi biner float tidak eksak untuk sebagian besar desimal.- Jangan gunakan
floatuntuk kalkulasi uang — gunakandecimal.Decimaluntuk presisi finansial yang benar.- String immutable — setiap operasi string menghasilkan objek baru. Gunakan
"".join(list)alih-alih concatenation dalam loop.Noneselalu dibandingkan denganis/is not, bukan==/!=.- Set kosong harus
set(), bukan{}— kurung kurawal kosong adalah dict kosong.- Mutable tidak bisa jadi key dict — gunakan tuple (immutable) sebagai key, bukan list.
isinstance()lebih baik daritype()— mengenali subkelas, lebih fleksibel untuk pengecekan tipe.- Konversi
bool("false")menghasilkanTrue— string non-kosong apapun adalah truthy, termasuk string"false","0", dan"None".