Perulangan #

Perulangan adalah mekanisme untuk mengeksekusi blok kode berulang kali. Python memiliki dua konstruksi perulangan utama — for dan while — tapi cara Python menggunakannya berbeda cukup signifikan dari bahasa seperti C, Java, atau JavaScript. Di Python, for loop bukan loop berbasis indeks, melainkan loop berbasis iterasi langsung atas elemen. Paradigma ini, digabung dengan built-in seperti enumerate, zip, dan comprehension, membuat kode perulangan Python jauh lebih ekspresif dan ringkas. Artikel ini membahas cara idiomatis menulis perulangan di Python — termasuk anti-pattern yang sering dibawa dari kebiasaan bahasa lain.

for Loop #

for loop di Python mengiterasi langsung atas elemen dari objek iterable — list, tuple, string, dict, set, generator, atau objek apapun yang mengimplementasikan protokol iterasi.

# Iterasi langsung — cara Python
buah = ["apel", "jeruk", "mangga"]
for item in buah:
    print(item)
# → apel
# → jeruk
# → mangga

# Iterasi string — karakter per karakter
for huruf in "Python":
    print(huruf, end=" ")
# → P y t h o n

# Iterasi tuple
for x, y in [(1, 2), (3, 4), (5, 6)]:   # unpacking langsung
    print(f"x={x}, y={y}")

# Iterasi set (urutan tidak dijamin)
for warna in {"merah", "hijau", "biru"}:
    print(warna)

Anti-Pattern: Iterasi via Indeks #

Kesalahan paling umum developer yang baru pindah ke Python adalah menggunakan indeks untuk iterasi — gaya yang lazim di C/Java tapi tidak idiomatis di Python:

buah = ["apel", "jeruk", "mangga"]

# ANTI-PATTERN: iterasi via indeks — tidak perlu di Python
for i in range(len(buah)):
    print(buah[i])

# BENAR: iterasi langsung atas elemen
for item in buah:
    print(item)

range() — Membuat Urutan Angka #

range() menghasilkan urutan angka secara lazy (tidak membuat list di memori). Tersedia dalam tiga bentuk:

# range(stop) — mulai dari 0, sampai stop-1
for i in range(5):
    print(i, end=" ")
# → 0 1 2 3 4

# range(start, stop) — mulai dari start, sampai stop-1
for i in range(2, 8):
    print(i, end=" ")
# → 2 3 4 5 6 7

# range(start, stop, step) — dengan langkah tertentu
for i in range(0, 20, 5):
    print(i, end=" ")
# → 0 5 10 15

# range mundur
for i in range(10, 0, -1):
    print(i, end=" ")
# → 10 9 8 7 6 5 4 3 2 1
# ANTI-PATTERN: range() untuk iterasi koleksi yang sudah ada
angka = [10, 20, 30, 40, 50]
for i in range(len(angka)):
    print(angka[i])

# BENAR: iterasi langsung
for n in angka:
    print(n)

# Kapan range() memang tepat digunakan:
# 1. Mengulang N kali tanpa butuh elemen
for _ in range(3):
    kirim_ping()

# 2. Menghasilkan angka dalam rentang tertentu
kuadrat = [i**2 for i in range(1, 11)]   # [1, 4, 9, 16, ..., 100]

enumerate() — Indeks dan Nilai Sekaligus #

Saat kamu memang butuh indeks dan nilainya, gunakan enumerate() — bukan range(len()):

buah = ["apel", "jeruk", "mangga"]

# ANTI-PATTERN: range(len()) hanya untuk mendapat indeks
for i in range(len(buah)):
    print(f"{i}: {buah[i]}")

# BENAR: enumerate() memberikan keduanya sekaligus
for i, item in enumerate(buah):
    print(f"{i}: {item}")
# → 0: apel
# → 1: jeruk
# → 2: mangga

# Mulai penomoran dari angka lain
for nomor, item in enumerate(buah, start=1):
    print(f"{nomor}. {item}")
# → 1. apel
# → 2. jeruk
# → 3. mangga

zip() — Iterasi Beberapa Koleksi Sekaligus #

zip() menggabungkan dua atau lebih iterable menjadi pasangan (tuple), berguna untuk iterasi paralel:

nama = ["Budi", "Ani", "Citra"]
nilai = [85, 92, 78]

# ANTI-PATTERN: iterasi via indeks untuk dua list
for i in range(len(nama)):
    print(f"{nama[i]}: {nilai[i]}")

# BENAR: zip() lebih bersih dan ekspresif
for n, v in zip(nama, nilai):
    print(f"{n}: {v}")
# → Budi: 85
# → Ani: 92
# → Citra: 78

# zip dengan tiga koleksi atau lebih
kota = ["Jakarta", "Surabaya", "Bandung"]
for n, v, k in zip(nama, nilai, kota):
    print(f"{n} dari {k}: {v}")
# Perilaku zip: berhenti di iterable terpendek
a = [1, 2, 3, 4, 5]
b = ["x", "y", "z"]
print(list(zip(a, b)))   # → [(1, 'x'), (2, 'y'), (3, 'z')] — elemen ke-4 dan 5 dibuang

# Gunakan itertools.zip_longest() jika ingin mempertahankan semua elemen
from itertools import zip_longest
print(list(zip_longest(a, b, fillvalue="-")))
# → [(1, 'x'), (2, 'y'), (3, 'z'), (4, '-'), (5, '-')]

while Loop #

while loop mengeksekusi blok kode selama kondisinya bernilai True. Digunakan saat jumlah iterasi tidak diketahui di awal.

# Pola dasar
hitung = 0
while hitung < 5:
    print(hitung)
    hitung += 1

# Input loop — terus minta input sampai valid
while True:
    jawaban = input("Lanjutkan? (y/n): ").lower()
    if jawaban in ("y", "n"):
        break
    print("Masukkan 'y' atau 'n'")

# Retry dengan batas maksimum
MAX_PERCOBAAN = 3
percobaan = 0
while percobaan < MAX_PERCOBAAN:
    berhasil = coba_koneksi()
    if berhasil:
        break
    percobaan += 1
    print(f"Gagal, percobaan {percobaan}/{MAX_PERCOBAAN}")
Selalu pastikan ada kondisi yang akan menghentikan while loop. Loop tanpa jalan keluar (infinite loop) akan membekukan program. Pola while True aman selama ada break yang reachable di dalam loop.

break, continue, dan pass #

break — Hentikan Loop Sepenuhnya #

# break menghentikan loop dari dalam
angka = [3, 7, 2, 9, 4, 1, 8]
target = 9

for n in angka:
    if n == target:
        print(f"Ditemukan: {n}")
        break   # hentikan loop begitu target ditemukan
else:
    print("Tidak ditemukan")   # dieksekusi hanya jika loop selesai TANPA break

continue — Lewati Iterasi Saat Ini #

# continue melompati sisa blok dan lanjut ke iterasi berikutnya
for i in range(10):
    if i % 2 == 0:
        continue   # lewati angka genap
    print(i, end=" ")
# → 1 3 5 7 9

# Contoh praktis: lewati baris kosong saat membaca file
baris_list = ["Budi", "", "Ani", "", "Citra"]
for baris in baris_list:
    if not baris.strip():
        continue   # lewati baris kosong
    proses(baris)

pass — Placeholder Kosong #

# pass adalah pernyataan yang tidak melakukan apapun
# berguna saat blok kode wajib ada tapi belum diimplementasi
for item in data:
    pass   # TODO: implementasi nanti

# Atau untuk kelas/fungsi kosong sementara
class DataProcessor:
    pass   # akan diisi nanti

def hitung_bonus():
    pass   # placeholder

else pada Loop — Fitur Jarang Diketahui #

Python memiliki klausa else untuk for dan while yang dieksekusi ketika loop selesai secara normal (tanpa break):

# for...else
def cari_prima(angka_list):
    for n in angka_list:
        for pembagi in range(2, int(n**0.5) + 1):
            if n % pembagi == 0:
                break   # bukan prima, hentikan loop dalam
        else:
            # loop dalam selesai tanpa break = tidak ada pembagi = prima
            print(f"{n} adalah bilangan prima")

cari_prima([2, 3, 4, 5, 6, 7, 8, 9, 10])
# → 2 adalah bilangan prima
# → 3 adalah bilangan prima
# → 5 adalah bilangan prima
# → 7 adalah bilangan prima
# while...else — praktis untuk pencarian dengan batas percobaan
import time

MAX_RETRY = 5
percobaan = 0
while percobaan < MAX_RETRY:
    if coba_koneksi_database():
        print("Koneksi berhasil")
        break
    percobaan += 1
    time.sleep(2)
else:
    # while selesai tanpa break = semua percobaan gagal
    raise ConnectionError(f"Gagal koneksi setelah {MAX_RETRY} percobaan")

List Comprehension #

List comprehension adalah cara ringkas dan Pythonic untuk membuat list baru dari iterasi, sering kali menggantikan loop for yang hanya membangun list:

# ANTI-PATTERN: loop untuk membangun list
kuadrat = []
for i in range(1, 11):
    kuadrat.append(i ** 2)

# BENAR: list comprehension — lebih ringkas dan biasanya lebih cepat
kuadrat = [i ** 2 for i in range(1, 11)]
print(kuadrat)   # → [1, 4, 9, 16, 25, 36, 49, 64, 81, 100]

# Dengan kondisi filter
genap = [i for i in range(20) if i % 2 == 0]
print(genap)   # → [0, 2, 4, 6, 8, 10, 12, 14, 16, 18]

# Transformasi string
nama_list = ["  budi  ", "ANI", "citra"]
bersih = [nama.strip().title() for nama in nama_list]
print(bersih)   # → ['Budi', 'Ani', 'Citra']

# Nested comprehension — matriks
matriks = [[i * j for j in range(1, 4)] for i in range(1, 4)]
print(matriks)
# → [[1, 2, 3], [2, 4, 6], [3, 6, 9]]

# Meratakan list bersarang
bersarang = [[1, 2, 3], [4, 5], [6, 7, 8, 9]]
datar = [item for sublist in bersarang for item in sublist]
print(datar)   # → [1, 2, 3, 4, 5, 6, 7, 8, 9]
# Dict comprehension
harga = {"apel": 5000, "jeruk": 8000, "mangga": 12000}

# Terapkan diskon 10% ke semua harga
harga_diskon = {nama: int(harga * 0.9) for nama, harga in harga.items()}
print(harga_diskon)
# → {'apel': 4500, 'jeruk': 7200, 'mangga': 10800}

# Set comprehension
angka = [1, 2, 2, 3, 3, 3, 4]
unik_kuadrat = {n ** 2 for n in angka}
print(unik_kuadrat)   # → {1, 4, 9, 16}

Generator Expression #

Generator expression mirip list comprehension tapi menggunakan tanda kurung biasa () dan menghasilkan nilai satu per satu secara lazy — tidak membuat seluruh koleksi di memori:

# List comprehension: membuat seluruh list di memori sekaligus
kuadrat_list = [i**2 for i in range(1_000_000)]   # ~8MB memori

# Generator expression: hitung satu per satu saat dibutuhkan
kuadrat_gen = (i**2 for i in range(1_000_000))    # hampir 0 memori

# Berguna untuk operasi yang hanya membutuhkan satu lintasan
total = sum(i**2 for i in range(1_000_000))   # efisien, tidak perlu list
ada_negatif = any(n < 0 for n in data)        # berhenti di elemen pertama yang negatif
semua_positif = all(n > 0 for n in data)      # berhenti di elemen pertama yang tidak positif

Fungsi Iterasi Built-in Penting #

Python menyediakan banyak fungsi built-in yang bekerja dengan iterasi:

angka = [3, 1, 4, 1, 5, 9, 2, 6, 5, 3]

# Agregasi
print(sum(angka))       # → 39
print(min(angka))       # → 1
print(max(angka))       # → 9
print(len(angka))       # → 10

# sorted() — kembalikan list baru yang terurut (tidak ubah asli)
print(sorted(angka))              # → [1, 1, 2, 3, 3, 4, 5, 5, 6, 9]
print(sorted(angka, reverse=True)) # → [9, 6, 5, 5, 4, 3, 3, 2, 1, 1]

# Urutkan berdasarkan kriteria custom
siswa = [("Budi", 85), ("Ani", 92), ("Citra", 78)]
urut_nilai = sorted(siswa, key=lambda s: s[1], reverse=True)
print(urut_nilai)   # → [('Ani', 92), ('Budi', 85), ('Citra', 78)]

# filter() — saring elemen yang memenuhi kondisi
positif = list(filter(lambda n: n > 0, [-3, 1, -2, 4, -1, 5]))
print(positif)   # → [1, 4, 5]

# map() — transformasi setiap elemen
kuadrat = list(map(lambda n: n**2, [1, 2, 3, 4, 5]))
print(kuadrat)   # → [1, 4, 9, 16, 25]

# any() dan all()
print(any(n > 8 for n in angka))    # → True  (ada yang > 8)
print(all(n > 0 for n in angka))    # → True  (semua > 0)

itertools — Kombinasi Iterasi Lanjutan #

Modul itertools menyediakan alat iterasi yang powerful dan efisien memori:

from itertools import chain, islice, product, combinations, permutations

# chain — gabungkan beberapa iterable menjadi satu
a = [1, 2, 3]
b = [4, 5, 6]
c = [7, 8, 9]
for n in chain(a, b, c):
    print(n, end=" ")
# → 1 2 3 4 5 6 7 8 9

# islice — ambil N elemen pertama dari iterable (lazy)
for n in islice(range(1_000_000), 5):
    print(n, end=" ")
# → 0 1 2 3 4

# product — perkalian kartesian (seperti nested for)
for warna, ukuran in product(["merah", "biru"], ["S", "M", "L"]):
    print(f"{warna}-{ukuran}", end="  ")
# → merah-S  merah-M  merah-L  biru-S  biru-M  biru-L

# combinations — kombinasi tanpa pengulangan
for combo in combinations([1, 2, 3, 4], 2):
    print(combo, end=" ")
# → (1,2) (1,3) (1,4) (2,3) (2,4) (3,4)

# permutations — semua susunan berbeda
for perm in permutations("ABC", 2):
    print("".join(perm), end=" ")
# → AB AC BA BC CA CB

Ringkasan #

  • Iterasi langsung, bukan via indeksfor item in koleksi bukan for i in range(len(koleksi)). Ini lebih bersih, lebih aman, dan lebih cepat.
  • enumerate() untuk mendapat indeks dan nilai sekaligus — menggantikan range(len()) dalam semua kasus.
  • zip() untuk iterasi paralel dua koleksi atau lebih — berhenti di iterable terpendek, gunakan zip_longest jika perlu semua elemen.
  • for...else dieksekusi saat loop selesai tanpa break — idiom yang bersih untuk pola “cari dan laporkan jika tidak ditemukan”.
  • List comprehension menggantikan loop yang hanya membangun list — lebih ringkas dan biasanya lebih cepat. Dict dan set comprehension juga tersedia.
  • Generator expression untuk data besar — sama seperti comprehension tapi lazy, hampir tidak menggunakan memori tambahan.
  • any() dan all() dengan generator expression berhenti lebih awal (short-circuit) — efisien untuk pengecekan kondisi pada koleksi besar.
  • itertools untuk pola iterasi lanjutan — chain, islice, product, combinations, permutations menghindari kebutuhan loop bersarang yang kompleks.

← Sebelumnya: Seleksi Kondisi   Berikutnya: Fungsi →

About | Author | Content Scope | Editorial Policy | Privacy Policy | Disclaimer | Contact