Komentar #

Komentar adalah teks dalam kode yang diabaikan sepenuhnya oleh interpreter Python — tidak dieksekusi, tidak mempengaruhi perilaku program. Fungsinya hanya satu: berkomunikasi dengan manusia yang membaca kode, baik itu rekan tim, kontributor open source, maupun dirimu sendiri enam bulan ke depan. Masalahnya, komentar yang ditulis sembarangan bisa lebih menyesatkan daripada tidak ada komentar sama sekali. Artikel ini membahas cara menulis komentar yang benar-benar membantu: kapan harus berkomentar, apa yang layak dijelaskan, format docstring yang dipakai ekosistem Python, dan anti-pattern komentar yang sebaiknya dihindari.

Komentar Satu Baris #

Komentar satu baris dimulai dengan tanda #. Semua teks setelah # hingga akhir baris akan diabaikan oleh interpreter. Ini adalah jenis komentar yang paling sering digunakan dalam kode sehari-hari.

# Ini adalah komentar satu baris
print("Hello, World!")

x = 10          # komentar inline — di akhir baris kode
y = x * 2       # hasil: 20

Komentar inline (di akhir baris) sebaiknya dipisahkan minimal dua spasi dari kode, lalu diikuti # dan teks. Ini adalah konvensi PEP 8.

# ANTI-PATTERN: komentar inline terlalu mepet
x=10 #nilai awal

# BENAR: dua spasi sebelum #, satu spasi setelah #
x = 10  # nilai awal

Komentar Multi-Baris #

Python tidak memiliki sintaks komentar multi-baris seperti /* ... */ di C atau Java. Cara yang umum digunakan adalah menyusun beberapa komentar # berturut-turut:

# Fungsi ini menghitung nilai akhir mahasiswa
# berdasarkan rata-rata ujian tengah semester (UTS),
# ujian akhir semester (UAS), dan nilai tugas harian.
# Bobot: UTS 30%, UAS 40%, Tugas 30%
def hitung_nilai_akhir(uts, uas, tugas):
    return (uts * 0.30) + (uas * 0.40) + (tugas * 0.30)

Triple-quoted string ("""...""" atau '''...''') kadang digunakan sebagai komentar multi-baris, tapi ini secara teknis adalah string literal yang tidak ditugaskan ke variabel manapun — bukan komentar sungguhan. Interpreter tetap memproses string tersebut (membuat objek string di memori), hanya saja hasilnya dibuang.

# ANTI-PATTERN: triple-quote sebagai komentar di tengah fungsi
def proses_data(data):
    """
    Langkah-langkah pemrosesan:
    1. Validasi input
    2. Normalisasi
    3. Simpan ke database
    """      # ← ini bukan komentar, ini string yang dibuang
    validasi(data)
    normalisasi(data)
    simpan(data)

# BENAR: gunakan # untuk komentar non-docstring
def proses_data(data):
    # Langkah-langkah pemrosesan:
    # 1. Validasi input
    # 2. Normalisasi
    # 3. Simpan ke database
    validasi(data)
    normalisasi(data)
    simpan(data)
Pengecualian: triple-quote memang tepat digunakan sebagai docstring — yaitu string pertama di dalam fungsi, kelas, atau modul. Docstring dibahas di bagian selanjutnya.

Docstring #

Docstring (documentation string) adalah string literal yang ditempatkan sebagai pernyataan pertama di dalam fungsi, kelas, metode, atau modul. Tidak seperti komentar # biasa, docstring disimpan oleh interpreter sebagai atribut __doc__ dari objek tersebut — artinya bisa diakses secara programatik melalui help() atau IDE.

def tambah(a, b):
    """Mengembalikan jumlah dari dua bilangan."""
    return a + b

# Akses docstring secara programatik
print(tambah.__doc__)   # → Mengembalikan jumlah dari dua bilangan.
help(tambah)            # → menampilkan dokumentasi lengkap di terminal

Docstring Satu Baris #

Digunakan untuk fungsi atau metode yang sederhana dan sudah jelas dari namanya. Ditulis dalam satu baris, diawali dan diakhiri """ pada baris yang sama.

def kuadrat(x):
    """Mengembalikan nilai x pangkat dua."""
    return x ** 2

def adalah_genap(n):
    """Mengembalikan True jika n adalah bilangan genap."""
    return n % 2 == 0

Docstring Multi-Baris #

Digunakan untuk fungsi, kelas, atau modul yang lebih kompleks. Baris pertama adalah ringkasan singkat (satu kalimat), diikuti baris kosong, lalu detail lebih lanjut.

def bagi(a, b):
    """
    Membagi dua bilangan dengan penanganan pembagian nol.

    Fungsi ini berbeda dari operator / biasa karena mengembalikan
    None alih-alih melempar ZeroDivisionError ketika pembagi adalah 0.

    Args:
        a (float): Bilangan yang dibagi (dividend).
        b (float): Bilangan pembagi (divisor).

    Returns:
        float | None: Hasil pembagian, atau None jika b adalah 0.

    Examples:
        >>> bagi(10, 2)
        5.0
        >>> bagi(10, 0)
        None
    """
    if b == 0:
        return None
    return a / b

Format Docstring #

Ada beberapa format penulisan docstring yang populer di ekosistem Python. Pilih satu format dan gunakan secara konsisten di seluruh proyek.

Google Style (Paling Umum) #

Format yang digunakan oleh Google dan banyak proyek modern. Lebih ringkas dan mudah dibaca secara visual.

def transfer_saldo(dari_akun, ke_akun, jumlah):
    """
    Memindahkan saldo antar dua akun bank.

    Fungsi ini bersifat atomic — jika salah satu operasi gagal,
    seluruh transfer dibatalkan dan saldo dikembalikan ke kondisi semula.

    Args:
        dari_akun (str): ID akun pengirim.
        ke_akun (str): ID akun penerima.
        jumlah (float): Jumlah saldo yang dipindahkan. Harus positif.

    Returns:
        bool: True jika transfer berhasil, False jika gagal.

    Raises:
        ValueError: Jika jumlah tidak positif.
        AccountNotFoundError: Jika salah satu akun tidak ditemukan.

    Examples:
        >>> transfer_saldo("ACC001", "ACC002", 500000)
        True
    """
    if jumlah <= 0:
        raise ValueError(f"Jumlah transfer harus positif, bukan {jumlah}")
    # implementasi ...

NumPy/SciPy Style #

Format yang digunakan oleh library ilmu data seperti NumPy, SciPy, dan pandas. Lebih verbose tapi sangat terstruktur — cocok untuk proyek data science.

def hitung_statistik(data):
    """
    Menghitung statistik deskriptif dari sekumpulan data numerik.

    Parameters
    ----------
    data : list of float
        Sekumpulan nilai numerik. Tidak boleh kosong.

    Returns
    -------
    dict
        Dictionary berisi kunci 'mean', 'median', 'std', 'min', 'max'.

    Raises
    ------
    ValueError
        Jika data adalah list kosong.

    Examples
    --------
    >>> hitung_statistik([1, 2, 3, 4, 5])
    {'mean': 3.0, 'median': 3.0, 'std': 1.58, 'min': 1, 'max': 5}
    """
    if not data:
        raise ValueError("Data tidak boleh kosong")
    # implementasi ...

Docstring untuk Kelas #

Docstring kelas menjelaskan tujuan kelas secara keseluruhan. Atribut instance biasanya didokumentasikan di sini atau di __init__.

class KeranjangBelanja:
    """
    Merepresentasikan keranjang belanja dalam sistem e-commerce.

    Keranjang menyimpan daftar item beserta jumlahnya dan
    menyediakan metode untuk menghitung total harga dengan
    memperhitungkan diskon dan pajak.

    Attributes:
        item (list): Daftar item dalam keranjang.
        diskon (float): Persentase diskon (0.0 hingga 1.0).
        pajak (float): Persentase pajak yang diterapkan.

    Examples:
        >>> keranjang = KeranjangBelanja()
        >>> keranjang.tambah_item("Buku Python", 75000, jumlah=2)
        >>> keranjang.total()
        150000
    """

    def __init__(self, diskon=0.0, pajak=0.11):
        """
        Inisialisasi keranjang belanja baru.

        Args:
            diskon (float): Persentase diskon. Default 0.0 (tidak ada diskon).
            pajak (float): Persentase pajak. Default 0.11 (PPN 11%).
        """
        self.item = []
        self.diskon = diskon
        self.pajak = pajak

Docstring untuk Modul #

Ditempatkan di baris paling atas file Python, sebelum semua import. Menjelaskan tujuan modul, isinya, dan cara penggunaan singkat.

"""
Modul utilitas untuk pemrosesan dan validasi data pengguna.

Modul ini menyediakan fungsi-fungsi untuk:
- Validasi format email, nomor telepon, dan NIK
- Normalisasi nama dan alamat
- Parsing data dari berbagai format input

Contoh penggunaan::

    from utils.user_validator import validasi_email, normalisasi_nama

    email = validasi_email("[email protected]")
    nama = normalisasi_nama("  john doe  ")

Dependencies:
    - re (stdlib)
    - phonenumbers >= 8.0

Author: Unis Badri
Created: 2024-01
"""

import re
import phonenumbers

Komentar yang Baik vs Komentar yang Buruk #

Ini adalah bagian yang paling sering diabaikan. Komentar buruk tidak hanya tidak berguna — komentar yang usang atau menyesatkan aktif merusak keterbacaan kode.

# ANTI-PATTERN: komentar yang hanya mengulang apa yang sudah jelas dari kode
x = x + 1  # tambahkan 1 ke x
nama = nama.strip()  # hapus whitespace dari nama
result = []  # buat list kosong

# BENAR: komentar yang menjelaskan MENGAPA, bukan APA
x = x + 1  # offset karena indeks API dimulai dari 1, bukan 0
nama = nama.strip()  # input dari form HTML kadang mengandung spasi tak terlihat
result = []  # list ini akan diisi secara lazy, hanya jika kondisi X terpenuhi
# ANTI-PATTERN: komentar yang berbohong (lebih buruk dari tidak ada komentar)
# Menghitung rata-rata nilai
def hitung_total(nilai_list):      # ← nama fungsi tidak sesuai komentar
    return sum(nilai_list)

# BENAR: komentar dan kode harus selalu sinkron
# Menjumlahkan semua nilai dalam list
def hitung_total(nilai_list):
    return sum(nilai_list)
# ANTI-PATTERN: kode yang di-comment out dan dibiarkan
def proses_pembayaran(order):
    # validasi_lama(order)        # ← kenapa ini dicomment? masih dipakai?
    # kirim_notif_v1(order)       # ← apakah ini masih relevan?
    validasi_baru(order)
    kirim_notif_v2(order)

# BENAR: hapus kode mati. Gunakan git untuk melihat history jika perlu.
def proses_pembayaran(order):
    validasi_baru(order)
    kirim_notif_v2(order)
Komentar yang paling berbahaya adalah komentar yang sudah usang — kode berubah tapi komentarnya tidak diperbarui. Saat membaca komentar yang bertentangan dengan kode, pembaca harus menebak mana yang benar. Jika kamu mengubah logika kode, selalu periksa apakah komentar di sekitarnya masih akurat.

Komentar untuk Penanda Khusus (TODO / FIXME / NOTE) #

Konvensi yang diakui luas di komunitas Python dan didukung banyak IDE adalah menggunakan tag tertentu dalam komentar untuk menandai pekerjaan yang belum selesai:

# TODO: tambahkan validasi untuk input berupa None
def hitung_diskon(harga, persen):
    return harga * (1 - persen / 100)

# FIXME: fungsi ini crash jika list kosong — belum sempat diperbaiki
def ambil_pertama(data):
    return data[0]

# NOTE: API endpoint ini akan deprecated di v3.0, gunakan /v3/users
def get_user_v2(user_id):
    return requests.get(f"/v2/users/{user_id}")

# HACK: solusi sementara untuk bug di library X versi 2.1.3
# Hapus ini setelah library diupgrade ke >= 2.2.0
hasil = hasil + 0.000001

Banyak IDE seperti VS Code dan PyCharm akan menyoroti tag-tag ini secara visual dan memungkinkan kamu melihat daftarnya sekaligus — jadi lebih mudah dilacak daripada komentar biasa.


Ringkasan #

  • Komentar # untuk kode, docstring untuk API — gunakan # di dalam body fungsi untuk menjelaskan logika, dan docstring di awal fungsi/kelas/modul untuk mendokumentasikan antarmuka publik.
  • Jelaskan MENGAPA, bukan APA — “tambah 1 ke x” tidak berguna; “offset karena indeks API dimulai dari 1” sangat berguna.
  • Jangan gunakan triple-quote sebagai komentar multi-baris di tengah fungsi — gunakan beberapa baris # berturut-turut.
  • Docstring satu baris untuk fungsi sederhana; docstring multi-baris dengan Args, Returns, Raises untuk fungsi kompleks.
  • Pilih satu format docstring dan konsisten — Google Style untuk proyek umum, NumPy Style untuk proyek data science.
  • Komentar usang lebih berbahaya dari tidak ada komentar — selalu perbarui komentar saat kamu mengubah logika kode.
  • Hapus kode yang di-comment out — gunakan git history untuk melihat kode lama, bukan tumpukan baris # yang tidak jelas.
  • Gunakan tag TODO/FIXME/NOTE untuk menandai pekerjaan yang belum selesai — didukung IDE dan lebih mudah dilacak daripada komentar biasa.

← Sebelumnya: Sintaks Utama   Berikutnya: Variabel →

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