Bab 68 — Portofolio, Karier, dan Terus Belajar

Seri A5 — Python Tingkat Ahli

CatatanDi bab ini, Anda akan:
  • Menyusun portofolio yang mudah dinilai orang lain, dan menulis README yang baik
  • Memeriksa kebersihan repo (lisensi, tes, rahasia) sebelum dipublikasikan
  • Mengetahui langkah pertama berkontribusi ke proyek open source
  • Mengenal jalur karier Python dan menyiapkan wawancara teknis dengan soal kode kecil
  • Menyusun cara mengikuti perkembangan Python dari sumber resmi, lalu menutup seluruh buku

Semua skrip bab ini ada di folder kode/bab68/. Di versi web, Anda juga bisa mengunduh semuanya sekaligus (zip).

Anda sudah menanam banyak: dari program “Halo” sampai pemroses citra terdistribusi. Tetapi hasil kebun yang tidak pernah sampai ke pasar tidak dikenal orang. Bab penutup ini tentang membawa hasil ke pasar: menata etalase (portofolio), memberi label yang jelas (README), memilih pasar yang cocok (karier), dan tetap menanam musim demi musim (terus belajar).

Catatan kejujuran. Bab ini tidak membuat repositori GitHub, tidak memposting apa pun, dan tidak mengirim data ke layanan mana pun; semua contoh dijalankan di komputer sendiri. Perintah Git dan GitHub yang ditampilkan di bawah tidak dijalankan saat buku dibuat; itu keputusan Anda di akun Anda sendiri. Bagian karier adalah gambaran umum yang kami susun dari isi buku, bukan data pasar kerja atau jaminan pekerjaan.

Jalur karier dan pintu masuknya dari isi buku ini.

Portofolio: etalase kemampuan Anda

Portofolio adalah kumpulan karya yang bisa dilihat orang tanpa harus mengenal Anda. Pemberi kerja atau pembimbing biasanya hanya punya beberapa menit; jadi sedikit karya yang rapi lebih baik daripada banyak karya setengah jadi.

Prinsip menyusunnya:

  1. Pilih 3 sampai 5 proyek unggulan, bukan semuanya. Pilih yang berbeda jenisnya (misalnya satu web, satu data/GIS, satu model, satu sistem terdistribusi).
  2. Tiap proyek menjawab empat pertanyaan: masalah apa, bagaimana cara kerjanya, bagaimana menjalankannya, dan apa hasilnya (angka, tangkapan layar, atau peta).
  3. Tunjukkan proses, bukan hanya hasil: riwayat commit yang jelas, tes, dan catatan keputusan menunjukkan cara berpikir.
  4. Jujur soal batas: tulis apa yang belum bisa dilakukan. Itu tanda kedewasaan, bukan kelemahan.
  5. Jaga data dan rahasia: pakai data tiruan atau data yang boleh dibagikan, dan pastikan tidak ada kata sandi atau kunci di repo (Bab 20 dan 49).

Menurut dokumentasi GitHub (docs.github.com, dibaca 2026-10-10), Anda juga bisa membuat README profil: repositori publik yang namanya persis sama dengan nama pengguna Anda, berisi README.md; isinya tampil di halaman profil. Itu tempat yang baik untuk perkenalan singkat dan tautan ke proyek unggulan. Langkahnya (tidak dijalankan di sini; dikerjakan sendiri):

git init
git add README.md
git commit -m "README awal"
# lalu buat repositori di GitHub atas nama Anda dan dorong dengan: git push

README yang baik

README adalah pintu depan repo. Dokumentasi GitHub menyebut README sebaiknya menjelaskan apa yang dilakukan proyek, mengapa berguna, cara memulai, di mana mendapat bantuan, dan siapa yang merawatnya; dokumentasi panjang cocok ditaruh di tempat lain (docs.github.com, dibaca 2026-10-10). GitHub mencari berkas ini di folder .github, folder utama, lalu docs (urutan itu), dan menampilkannya otomatis, dengan daftar isi dari judul-judulnya.

Berikut README contoh untuk proyek bersambung kita, dibuat oleh skrip lalu diperiksa daftar periksa otomatis:

01_readme_contoh.py
# Bab 68 - README yang baik: contoh nyata, lalu diperiksa otomatis
import re

proyek = {
    "nama": "sipenhut",
    "satu_kalimat": "Sistem informasi sederhana untuk mencatat dan merangkum data hutan, kebun, kolam, dan kandang.",
    "fitur": [
        "Mencatat pohon, panen, ikan, dan ternak (data contoh fiktif)",
        "Merangkum per petak dan menyimpannya sebagai CSV",
        "Memproses foto drone dengan banyak worker",
    ],
    "kebutuhan": "Python 3.12 atau lebih baru",
    "contoh_kode": 'from sipenhut import ringkas\n\nprint(ringkas("data/pohon.csv"))',
    "lisensi": "MIT",
}

README = f"""# {proyek['nama']}

{proyek['satu_kalimat']}

## Fitur

{chr(10).join('- ' + f for f in proyek['fitur'])}

## Pemasangan

Kebutuhan: {proyek['kebutuhan']}.

~~~bash
python -m venv .venv
.venv/Scripts/activate        # Windows; di Linux/macOS: source .venv/bin/activate
pip install -e .
~~~

## Pemakaian singkat

~~~python
{proyek['contoh_kode']}
~~~

## Menjalankan tes

~~~bash
pytest
~~~

## Berkontribusi

Laporan masalah dan usulan perbaikan dipersilakan lewat Issues.

## Lisensi

{proyek['lisensi']} (lihat berkas LICENSE). Semua data contoh adalah data tiruan.
"""

print(README)
print("=" * 40)


def periksa_readme(teks):
    """Daftar periksa README: pembaca baru harus bisa menjawab empat pertanyaan dalam semenit."""
    bagian = re.findall(r"^## (.+)$", teks, re.MULTILINE)
    return {
        "ada judul (H1)": teks.lstrip().startswith("# "),
        "ada penjelasan satu kalimat": len(teks.splitlines()[2]) > 20,
        "ada bagian Pemasangan": "Pemasangan" in bagian,
        "ada contoh pemakaian berupa kode": "~~~python" in teks,
        "ada cara menjalankan tes": "Menjalankan tes" in bagian,
        "ada lisensi": "Lisensi" in bagian,
        "tanpa kata sandi atau kunci": not re.search(r"(password|passwd|api[_-]?key|secret)\s*[:=]", teks, re.I),
        "tanpa sisa TODO": "TODO" not in teks,
    }


for butir, lulus in periksa_readme(README).items():
    print(f"[{'OK' if lulus else '--'}] {butir}")
# sipenhut

Sistem informasi sederhana untuk mencatat dan merangkum data hutan, kebun, kolam, dan kandang.

## Fitur

- Mencatat pohon, panen, ikan, dan ternak (data contoh fiktif)
- Merangkum per petak dan menyimpannya sebagai CSV
- Memproses foto drone dengan banyak worker

## Pemasangan

Kebutuhan: Python 3.12 atau lebih baru.

~~~bash
python -m venv .venv
.venv/Scripts/activate        # Windows; di Linux/macOS: source .venv/bin/activate
pip install -e .
~~~

## Pemakaian singkat

~~~python
from sipenhut import ringkas

print(ringkas("data/pohon.csv"))
~~~

## Menjalankan tes

~~~bash
pytest
~~~

## Berkontribusi

Laporan masalah dan usulan perbaikan dipersilakan lewat Issues.

## Lisensi

MIT (lihat berkas LICENSE). Semua data contoh adalah data tiruan.

========================================
[OK] ada judul (H1)
[OK] ada penjelasan satu kalimat
[OK] ada bagian Pemasangan
[OK] ada contoh pemakaian berupa kode
[OK] ada cara menjalankan tes
[OK] ada lisensi
[OK] tanpa kata sandi atau kunci
[OK] tanpa sisa TODO

Perhatikan urutannya: judul, satu kalimat yang bisa dipahami orang awam, fitur, cara memasang, contoh pemakaian berupa kode, cara menjalankan tes, ajakan berkontribusi, dan lisensi. Kalimat terakhir menyatakan bahwa data contoh adalah tiruan, supaya tidak disangka data sungguhan. (Pagar kode di README contoh ditulis dengan ~~~ agar tidak bertabrakan dengan pagar kode buku ini.) Daftar periksa mudah ditiru untuk repo Anda sendiri.

TipTIPS

Uji README Anda dengan orang yang belum pernah melihat proyeknya: minta ia memasang dan menjalankan contoh hanya dengan membaca README. Setiap kali ia tersangkut, itulah baris yang harus Anda perbaiki.

Memeriksa kebersihan repo

Sebelum membuka repo ke publik, periksa hal-hal dasar. Skrip ini membuat repo contoh yang sengaja belum sempurna lalu memeriksanya:

02_periksa_repo.py
# Bab 68 - Memeriksa "kebersihan" repo sebelum dijadikan portofolio
import re
import shutil
from pathlib import Path

folder = Path(__file__).parent / "_tmp" / "repo_contoh"
shutil.rmtree(folder, ignore_errors=True)
(folder / "src" / "sipenhut").mkdir(parents=True)
(folder / "tests").mkdir()

# Repo contoh BELUM sempurna: sengaja ada kekurangan agar pemeriksanya punya yang ditemukan
(folder / "README.md").write_text("# sipenhut\n\nSistem informasi sederhana.\n", encoding="utf-8")
(folder / "pyproject.toml").write_text('[project]\nname = "sipenhut"\nversion = "0.1.0"\n', encoding="utf-8")
(folder / "src" / "sipenhut" / "__init__.py").write_text('"""Paket contoh."""\n', encoding="utf-8")
(folder / "tests" / "test_dasar.py").write_text("def test_jalan():\n    assert 1 + 1 == 2\n", encoding="utf-8")
(folder / "konfigurasi.py").write_text('TOKEN_LAYANAN = "contoh-bukan-rahasia-sungguhan"\n', encoding="utf-8")

POLA_RAHASIA = re.compile(r"(token|password|passwd|api[_-]?key|secret)\w*\s*=\s*[\"'][^\"']+[\"']", re.I)


def periksa(folder):
    ada = lambda *nama: any((folder / n).exists() for n in nama)
    berkas_py = [p for p in folder.rglob("*.py")]
    rahasia = [p.name for p in berkas_py if POLA_RAHASIA.search(p.read_text(encoding="utf-8"))]
    readme = (folder / "README.md").read_text(encoding="utf-8") if ada("README.md") else ""
    return [
        ("README.md ada", ada("README.md")),
        ("README menjelaskan cara memasang dan memakai", "Pemasangan" in readme and "Pemakaian" in readme),
        ("LICENSE ada", ada("LICENSE", "LICENSE.md", "LICENSE.txt")),
        ("pyproject.toml ada", ada("pyproject.toml")),
        ("folder tests ada dan berisi tes", any((folder / "tests").glob("test_*.py"))),
        (".gitignore ada", ada(".gitignore")),
        (f"tanpa rahasia di kode (ditemukan: {rahasia or 'tidak ada'})", not rahasia),
    ]


hasil = periksa(folder)
for butir, lulus in hasil:
    print(f"[{'OK' if lulus else '--'}] {butir}")
print(f"\nSkor: {sum(l for _, l in hasil)} dari {len(hasil)}")
print("Perbaiki dulu butir bertanda [--] sebelum repo dipublikasikan.")
[OK] README.md ada
[--] README menjelaskan cara memasang dan memakai
[--] LICENSE ada
[OK] pyproject.toml ada
[OK] folder tests ada dan berisi tes
[--] .gitignore ada
[--] tanpa rahasia di kode (ditemukan: ['konfigurasi.py'])

Skor: 3 dari 7
Perbaiki dulu butir bertanda [--] sebelum repo dipublikasikan.

Skor 3 dari 7: repo contoh punya README, pyproject.toml, dan tes, tetapi README-nya belum menjelaskan pemasangan dan pemakaian, tidak ada LICENSE (tanpa lisensi, orang lain pada dasarnya tidak berhak memakai kode Anda; Bab 63), tidak ada .gitignore, dan ada string mirip rahasia di konfigurasi.py. Contoh itu hanya berisi teks “bukan rahasia sungguhan”, tetapi pemeriksa sederhana ini tidak bisa membedakan, sama seperti alat pemindai rahasia sungguhan: kebiasaan terbaik adalah tidak pernah menulis rahasia di kode, memakai variabel lingkungan, dan memasang pemindai (misalnya di CI, Bab 48).

PeringatanAWAS

Jika rahasia (kata sandi, kunci API) pernah ter-commit, menghapusnya dari berkas tidak cukup: riwayat Git masih menyimpannya. Anggap rahasia itu bocor: cabut dan buat yang baru, baru bersihkan riwayatnya.

Berkontribusi ke open source

Berkontribusi adalah cara terbaik belajar membaca kode orang lain, dan tanda yang bagus di portofolio. Kontribusi bukan hanya kode: menurut Open Source Guide (opensource.guide, dibaca 2026-10-10), dokumentasi, terjemahan, tutorial, menjawab pertanyaan, dan menyortir laporan masalah juga dihitung.

Urutan yang dianjurkan panduan itu, kami ringkas:

  1. Mulai dari proyek yang sudah Anda pakai, dan pantau (watch) laporan masalah dan pull request-nya untuk memahami kebiasaannya.
  2. Periksa berkas penting: LICENSE (tanpa lisensi, proyek itu bukan open source), README, CONTRIBUTING (aturan berkontribusi), dan CODE_OF_CONDUCT. Lihat juga apakah pengelolanya aktif menanggapi.
  3. Cari masalah yang ramah pemula, dan beri komentar bila Anda mengerjakannya agar tidak ada kerja ganda.
  4. Perbaikan kecil (salah ketik, tautan rusak) cocok langsung dikirim sebagai pull request; perubahan besar sebaiknya didiskusikan lewat issue dulu.
  5. Komunikasi: beri konteks, jaga diskusi tetap terbuka (publik), bersabar; bila seminggu tak ada tanggapan, tanyakan kembali dengan sopan di utas yang sama.

Untuk Python sendiri ada Python Developer’s Guide (devguide.python.org): jalur dokumentasi, memperbaiki galat, dan menyortir issue, ditambah kelompok mentoring bagi kontributor baru; semua interaksi di infrastruktur PSF tunduk pada Kode Etik PSF (dibaca 2026-10-10). Alur Git dasarnya sudah Anda pelajari di Bab 20: fork, branch, commit, pull request.

Jalur karier Python

Python dipakai di banyak bidang. Tabel berikut memetakan lima jalur ke bab dan proyek di buku ini. Ini gambaran umum, bukan data lowongan; kebutuhan sebenarnya berbeda menurut kota, perusahaan, dan waktu, jadi baca beberapa deskripsi lowongan nyata sebelum menentukan fokus.

Jalur Apa yang dikerjakan Bab di buku ini Proyek portofolio
Data / analisis membersihkan, menganalisis, dan menyajikan data 23-29, 50, 53 laporan analisis dan dasbor
GIS / geospasial peta, citra satelit, analisis ruang 38-40, 51-52 peta interaktif, pipeline citra
Web / backend API, layanan, basis data 36, 42-43, 45-49 API terdeploy dengan tes dan CI
AI / ML model, evaluasi, aplikasi LLM, agent 54-62 model dengan penjelasan, asisten dokumen
Riset / ilmiah analisis yang bisa direproduksi, publikasi 26-29, 58 laporan reproduktif dengan data dan kode terbuka

Dua pengamatan lintas jalur: kemampuan dasar (Bab 1-35) dibutuhkan semua jalur, dan kebiasaan rekayasa (tes, Git, kemasan, deployment) sering lebih menentukan daripada pustaka tertentu, karena pustaka berganti sedangkan kebiasaan menetap.

Wawancara teknis: latihan soal kode kecil

Wawancara teknis sering meminta Anda menulis fungsi kecil sambil berpikir keras. Yang dinilai bukan hanya jawaban, melainkan cara berpikir: memahami soal, memeriksa kasus tepi, memilih struktur data, dan menjelaskan kompleksitas. Kebiasaan yang membantu: ulangi soal dengan kata sendiri, mulai dari contoh kecil, tulis solusi sederhana dulu lalu perbaiki, dan uji sendiri.

03_wawancara_larik_teks.py
# Bab 68 - Latihan wawancara teknis (1): larik, teks, dan kamus
from collections import defaultdict


# Soal 1: dua bilangan yang jumlahnya sama dengan target. Kembalikan pasangan indeksnya.
# Pendekatan: satu kali jalan memakai kamus {nilai: indeks}  ->  waktu O(n), bukan O(n^2)
def dua_jumlah(angka, target):
    terlihat = {}
    for i, a in enumerate(angka):
        sisa = target - a
        if sisa in terlihat:
            return terlihat[sisa], i
        terlihat[a] = i
    return None


# Soal 2: kelompokkan kata yang merupakan anagram (huruf sama, urutan beda).
# Kunci kamus: huruf kata yang diurutkan.
def kelompok_anagram(kata):
    kelompok = defaultdict(list)
    for k in kata:
        kelompok["".join(sorted(k))].append(k)
    return sorted(sorted(g) for g in kelompok.values())


# Soal 3: gabungkan rentang yang tumpang tindih, misalnya jangkauan sensor.
def gabung_rentang(rentang):
    hasil = []
    for awal, akhir in sorted(rentang):
        if hasil and awal <= hasil[-1][1]:                  # tumpang tindih dengan yang terakhir
            hasil[-1][1] = max(hasil[-1][1], akhir)
        else:
            hasil.append([awal, akhir])
    return hasil


# Soal 4: apakah kalimat palindrom (abaikan spasi, huruf besar, dan tanda baca)?
def palindrom(kalimat):
    bersih = [c.lower() for c in kalimat if c.isalnum()]
    return bersih == bersih[::-1]


print("1.", dua_jumlah([2, 7, 11, 15], 9), dua_jumlah([3, 3], 6), dua_jumlah([1, 2], 10))
print("2.", kelompok_anagram(["jati", "tija", "meranti", "sengon", "nongse", "tiaj"]))
print("3.", gabung_rentang([(8, 10), (1, 3), (2, 6), (15, 18), (17, 20)]))
print("4.", palindrom("Kasur rusak"), palindrom("Python"))

# Uji otomatis kecil: kebiasaan baik di wawancara adalah menguji kasus tepi sendiri
assert dua_jumlah([], 5) is None
assert gabung_rentang([]) == []
assert gabung_rentang([(1, 4), (4, 5)]) == [[1, 5]]        # bersinggungan dihitung menyatu
assert palindrom("") is True
print("kasus tepi lulus")
1. (0, 1) (0, 1) None
2. [['jati', 'tiaj', 'tija'], ['meranti'], ['nongse', 'sengon']]
3. [[1, 6], [8, 10], [15, 20]]
4. True False
kasus tepi lulus
  • Soal 1 (dua jumlah): satu kali jalan dengan kamus {nilai: indeks} menjadi O(n); cara pertama yang terpikir (dua perulangan bersarang) O(n^2). (0, 1) untuk [2, 7, 11, 15] dan target 9 (2 + 7), dan None bila tak ada pasangan.
  • Soal 2 (anagram): kunci kamus adalah huruf yang diurutkan; jati, tija, tiaj satu kelompok.
  • Soal 3 (gabung rentang): urutkan dulu, lalu cukup bandingkan dengan rentang terakhir; (2, 6) menelan (1, 3), dan (17, 20) menyatu dengan (15, 18).
  • Soal 4 (palindrom): bersihkan karakter non-huruf-angka dulu, lalu bandingkan dengan balikannya.
  • Tiga assert terakhir menguji kasus tepi (daftar kosong, rentang yang bersinggungan, teks kosong).
04_wawancara_struktur_data.py
# Bab 68 - Latihan wawancara teknis (2): struktur data dan pemilihan algoritma
import bisect
from collections import OrderedDict, deque


# Soal 5: cache LRU (Least Recently Used): buang yang paling lama tidak dipakai.
class CacheLRU:
    def __init__(self, kapasitas):
        self.kapasitas = kapasitas
        self.isi = OrderedDict()

    def ambil(self, kunci):
        if kunci not in self.isi:
            return None
        self.isi.move_to_end(kunci)                  # ditandai baru saja dipakai
        return self.isi[kunci]

    def simpan(self, kunci, nilai):
        self.isi[kunci] = nilai
        self.isi.move_to_end(kunci)
        if len(self.isi) > self.kapasitas:
            self.isi.popitem(last=False)             # buang yang paling lama


# Soal 6: kurung seimbang, mis. rumus "(a + [b * c])"
def kurung_seimbang(teks):
    pasangan = {")": "(", "]": "[", "}": "{"}
    tumpukan = []
    for c in teks:
        if c in "([{":
            tumpukan.append(c)
        elif c in pasangan:
            if not tumpukan or tumpukan.pop() != pasangan[c]:
                return False
    return not tumpukan


# Soal 7: pencarian biner pada daftar terurut (O(log n)); pakai bisect dari pustaka standar
def cari_indeks(terurut, nilai):
    i = bisect.bisect_left(terurut, nilai)
    return i if i < len(terurut) and terurut[i] == nilai else -1


# Soal 8: jarak terpendek di grid (BFS), mis. rute di petak kebun; '#' = pagar
def jarak_terpendek(grid, mulai, tujuan):
    antrean = deque([(mulai, 0)])
    terlihat = {mulai}
    while antrean:
        (r, c), jarak = antrean.popleft()
        if (r, c) == tujuan:
            return jarak
        for dr, dc in ((1, 0), (-1, 0), (0, 1), (0, -1)):
            rr, cc = r + dr, c + dc
            if 0 <= rr < len(grid) and 0 <= cc < len(grid[0]) and grid[rr][cc] != "#" and (rr, cc) not in terlihat:
                terlihat.add((rr, cc))
                antrean.append(((rr, cc), jarak + 1))
    return -1


cache = CacheLRU(2)
cache.simpan("A", 1)
cache.simpan("B", 2)
cache.ambil("A")                                     # A baru dipakai, jadi B yang paling lama
cache.simpan("C", 3)                                 # kapasitas penuh: B dibuang
print("5.", cache.ambil("A"), cache.ambil("B"), cache.ambil("C"))
print("6.", kurung_seimbang("(a + [b * c])"), kurung_seimbang("(a + [b * c)]"))
print("7.", cari_indeks([10, 20, 30, 40], 30), cari_indeks([10, 20, 30, 40], 35))
kebun = ["..#.",
         "..#.",
         "....",
         "#..."]
print("8.", jarak_terpendek(kebun, (0, 0), (0, 3)), jarak_terpendek(["..#", "###", "..."], (0, 0), (2, 2)))
5. 1 None 3
6. True False
7. 2 -1
8. 7 -1
  • Soal 5 (cache LRU): OrderedDict menjaga urutan pemakaian; setelah A dipakai, yang dibuang adalah B (hasil 1 None 3).
  • Soal 6 (kurung seimbang): tumpukan (stack); (a + [b * c)] salah karena urutan penutupnya tertukar.
  • Soal 7 (pencarian biner): bisect dari pustaka standar, O(log n); -1 bila tak ada.
  • Soal 8 (jarak terpendek di grid): breadth-first search dengan antrean deque; jarak 7 langkah di kebun contoh, dan -1 bila jalan tertutup pagar.
CatatanINGAT

Latihan wawancara yang baik bukan menghafal jawaban, tetapi mengenali pola (kamus untuk pencarian cepat, tumpukan untuk pasangan bersarang, antrean untuk penelusuran melebar, pengurutan lalu satu kali jalan) dan menjelaskan pilihan Anda dengan kompleksitasnya.

Terus belajar: sumber resmi dan kebiasaan

Python dan pustakanya terus berubah. Cara mengikutinya tanpa kewalahan:

  • Baca “What’s New” tiap rilis (docs.python.org/3/whatsnew/): ringkasan resmi fitur baru dan yang dihapus. Rilis tahunan Python mengikuti jadwal yang dituliskan di PEP (misalnya PEP 745 untuk 3.14: rilis final 3.14.0 dijadwalkan 7 Oktober 2025, dan dukungan keamanan berlanjut sampai kira-kira Oktober 2030, dibaca 2026-10-10).
  • Ikuti blog resmi Python Insider (blog.python.org). Saat bab ini ditulis, blog itu melaporkan Python 3.15.0 final dirilis 9 Oktober 2026; buku ini memakai 3.14 sebagai acuan, jadi membaca “What’s New in Python 3.15” adalah latihan yang baik.
  • Kenali PEP (Python Enhancement Proposal, peps.python.org): dokumen usulan perubahan bahasa. PEP 8 adalah panduan gaya; PEP lain menjelaskan mengapa fitur dirancang begitu.
  • Dokumentasi resmi pustaka lebih andal daripada artikel acak; periksa tanggal dan versinya.
  • Bergabung dengan komunitas: forum diskusi resmi (discuss.python.org) dan konferensi (misalnya situs pycon.org).
  • Kebiasaan: satu proyek kecil tiap bulan; baca kode pustaka yang Anda pakai; catat apa yang dipelajari.

Semua tautan di atas diperiksa oleh skrip berikut. Keluarannya diambil sekali pada 2026-10-10 (@statis): tautan bisa berubah, jadi periksa lagi bila ada yang gagal.

05_periksa_tautan.py
# Bab 68 - Memeriksa bahwa tautan sumber belajar benar-benar ada
import requests

TAUTAN = {
    "Situs resmi Python": "https://www.python.org/",
    "Unduh Python": "https://www.python.org/downloads/",
    "Dokumentasi Python 3": "https://docs.python.org/3/",
    "Apa yang Baru (What's New)": "https://docs.python.org/3/whatsnew/",
    "What's New 3.14": "https://docs.python.org/3/whatsnew/3.14.html",
    "Indeks PEP": "https://peps.python.org/",
    "PEP 8 (gaya penulisan)": "https://peps.python.org/pep-0008/",
    "PEP 745 (jadwal rilis 3.14)": "https://peps.python.org/pep-0745/",
    "Blog resmi Python Insider": "https://blog.python.org/",
    "Panduan Pengembang Python": "https://devguide.python.org/",
    "Forum diskusi Python": "https://discuss.python.org/",
    "Panduan Pengemasan Python": "https://packaging.python.org/",
    "PyPI": "https://pypi.org/",
    "Kode sumber CPython": "https://github.com/python/cpython",
    "Panduan Open Source (GitHub)": "https://opensource.guide/how-to-contribute/",
    "Tentang README (GitHub Docs)": "https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/about-readmes",
    "Memilih lisensi": "https://choosealicense.com/",
    "Versi Semantik": "https://semver.org/",
}

ok = 0
for nama, url in TAUTAN.items():
    try:
        jawab = requests.get(url, timeout=20, headers={"User-Agent": "buku-python-total (pemeriksa tautan)"}, stream=True)
        status = jawab.status_code
        jawab.close()
    except requests.RequestException as e:
        status = type(e).__name__
    ok += status == 200
    print(f"{str(status):>4}  {nama}")
print(f"\n{ok} dari {len(TAUTAN)} tautan menjawab 200 (ada)")
 200  Situs resmi Python
 200  Unduh Python
 200  Dokumentasi Python 3
 200  Apa yang Baru (What's New)
 200  What's New 3.14
 200  Indeks PEP
 200  PEP 8 (gaya penulisan)
 200  PEP 745 (jadwal rilis 3.14)
 200  Blog resmi Python Insider
 200  Panduan Pengembang Python
 200  Forum diskusi Python
 200  Panduan Pengemasan Python
 200  PyPI
 200  Kode sumber CPython
 200  Panduan Open Source (GitHub)
 200  Tentang README (GitHub Docs)
 200  Memilih lisensi
 200  Versi Semantik

18 dari 18 tautan menjawab 200 (ada)

Kedelapan belas tautan menjawab 200, artinya halamannya ada saat diperiksa. Itu bukti bahwa tautan ada, bukan bahwa isinya sesuai selera Anda; bacalah sendiri. Kami juga tidak memasukkan tautan tanpa memeriksanya.

Proyek Bersambung A5: seluruh proyek sebagai portofolio

Langkah terakhir proyek bersambung kita: merangkum seluruh perjalanan, 68 bab dalam 13 seri, menjadi satu halaman portofolio dengan peta kemampuan.

06_proyek_portofolio.py
# Bab 68 - Proyek A5: merangkum seluruh proyek menjadi halaman portofolio
SERI = [
    # (tingkat, seri, bab_awal, bab_akhir, kemampuan inti, bukti di repo)
    ("Basic", "B1", 1, 4, "dasar komputer, berpikir algoritmis, terminal", "catatan belajar"),
    ("Basic", "B2", 5, 10, "variabel, alur kontrol, struktur data, fungsi", "pencatat data lapangan"),
    ("Basic", "B3", 11, 15, "modul, error, berkas, CSV/JSON, laporan kantor", "rekap otomatis Excel/PDF"),
    ("Intermediate", "I1", 16, 20, "OOP, venv, tes, kualitas kode, Git", "paket dengan tes dan CI"),
    ("Intermediate", "I2", 21, 25, "API, regex, pandas, database", "pipeline data + SQL"),
    ("Intermediate", "I3", 26, 29, "statistik, regresi, kualitatif, riset reproduktif", "laporan analisis"),
    ("Intermediate", "I4", 30, 35, "generator, decorator, tipe, Pydantic, async", "kode idiomatik bertipe"),
    ("Intermediate", "I5", 36, 43, "web, GIS, otomasi, dasbor", "aplikasi web + peta + dasbor"),
    ("Advanced", "A1", 44, 49, "performa, pengemasan, arsitektur, deployment, keamanan", "layanan siap produksi"),
    ("Advanced", "A2", 50, 53, "Polars/DuckDB, citra cloud-native, IoT, Dask", "pipeline data skala besar"),
    ("Advanced", "A3", 54, 59, "ML, deep learning, visi komputer, optimisasi", "model deteksi + penjelasan"),
    ("Advanced", "A4", 60, 63, "LLM, RAG, agent AI, lisensi dan etika", "asisten dokumen + agent"),
    ("Advanced", "A5", 64, 68, "metaprogramming, internals, performa native/GPU, terdistribusi", "pemroses citra terdistribusi"),
]

print("# Portofolio: Sistem Informasi Hutan, Kebun, Pertanian, Perikanan, Peternakan\n")
print("| Tingkat | Seri | Bab | Kemampuan inti | Bukti di repo |")
print("|---|---|---|---|---|")
total_bab = 0
for tingkat, seri, awal, akhir, kemampuan, bukti in SERI:
    total_bab += akhir - awal + 1
    print(f"| {tingkat} | {seri} | {awal}-{akhir} | {kemampuan} | {bukti} |")

print(f"\nJumlah seri: {len(SERI)}; jumlah bab: {total_bab}.")

# Pemeriksaan konsistensi: bab harus bersambung tanpa lubang atau tumpang tindih
berurutan = all(SERI[i][3] + 1 == SERI[i + 1][2] for i in range(len(SERI) - 1))
print("bab bersambung tanpa lubang:", berurutan, "| mulai di bab", SERI[0][2], "| berakhir di bab", SERI[-1][3])

print("\nTiga proyek unggulan untuk disorot di profil GitHub:")
for i, (judul, alasan) in enumerate([
    ("Pemroses citra terdistribusi (Bab 67)", "menunjukkan antrean, worker, coba-ulang, dan biaya"),
    ("Aplikasi web, peta, dan dasbor (Bab 36-43)", "mudah dilihat orang, bisa diberi tangkapan layar"),
    ("Model deteksi dengan penjelasan (Bab 54-58)", "menunjukkan evaluasi jujur, bukan hanya akurasi"),
], 1):
    print(f"  {i}. {judul}: {alasan}")
# Portofolio: Sistem Informasi Hutan, Kebun, Pertanian, Perikanan, Peternakan

| Tingkat | Seri | Bab | Kemampuan inti | Bukti di repo |
|---|---|---|---|---|
| Basic | B1 | 1-4 | dasar komputer, berpikir algoritmis, terminal | catatan belajar |
| Basic | B2 | 5-10 | variabel, alur kontrol, struktur data, fungsi | pencatat data lapangan |
| Basic | B3 | 11-15 | modul, error, berkas, CSV/JSON, laporan kantor | rekap otomatis Excel/PDF |
| Intermediate | I1 | 16-20 | OOP, venv, tes, kualitas kode, Git | paket dengan tes dan CI |
| Intermediate | I2 | 21-25 | API, regex, pandas, database | pipeline data + SQL |
| Intermediate | I3 | 26-29 | statistik, regresi, kualitatif, riset reproduktif | laporan analisis |
| Intermediate | I4 | 30-35 | generator, decorator, tipe, Pydantic, async | kode idiomatik bertipe |
| Intermediate | I5 | 36-43 | web, GIS, otomasi, dasbor | aplikasi web + peta + dasbor |
| Advanced | A1 | 44-49 | performa, pengemasan, arsitektur, deployment, keamanan | layanan siap produksi |
| Advanced | A2 | 50-53 | Polars/DuckDB, citra cloud-native, IoT, Dask | pipeline data skala besar |
| Advanced | A3 | 54-59 | ML, deep learning, visi komputer, optimisasi | model deteksi + penjelasan |
| Advanced | A4 | 60-63 | LLM, RAG, agent AI, lisensi dan etika | asisten dokumen + agent |
| Advanced | A5 | 64-68 | metaprogramming, internals, performa native/GPU, terdistribusi | pemroses citra terdistribusi |

Jumlah seri: 13; jumlah bab: 68.
bab bersambung tanpa lubang: True | mulai di bab 1 | berakhir di bab 68

Tiga proyek unggulan untuk disorot di profil GitHub:
  1. Pemroses citra terdistribusi (Bab 67): menunjukkan antrean, worker, coba-ulang, dan biaya
  2. Aplikasi web, peta, dan dasbor (Bab 36-43): mudah dilihat orang, bisa diberi tangkapan layar
  3. Model deteksi dengan penjelasan (Bab 54-58): menunjukkan evaluasi jujur, bukan hanya akurasi

Tabel inilah kerangka halaman “Tentang proyek” Anda: tiap seri punya kemampuan inti dan satu bukti di repo. Pengecekan menunjukkan bab bersambung tanpa lubang dari 1 sampai 68. Tiga proyek unggulan yang disarankan di bawah tabel adalah contoh; pilihlah yang paling Anda banggakan dan paling mudah dipahami orang lain.

Latihan

  1. Tulis README untuk satu proyek Anda dari buku ini memakai kerangka di skrip 01, lalu jalankan daftar periksanya. Minta satu teman memasangnya hanya dari README dan catat di mana ia tersangkut.
  2. Jalankan 02_periksa_repo.py pada folder proyek Anda sendiri (ubah variabel folder). Perbaiki semua butir [--].
  3. Kerjakan soal 1 sampai 4 tanpa melihat jawabannya, lalu bandingkan. Tambahkan dua kasus tepi Anda sendiri untuk tiap soal.
  4. Tantangan: pilih satu proyek open source yang Anda pakai, baca CONTRIBUTING-nya, dan tulis (tanpa mengirim apa pun) satu usulan perbaikan dokumentasi lengkap dengan alasannya. Kirimkan hanya bila Anda siap dan sudah mematuhi aturan proyek itu.

Ringkasan Bab

  • Portofolio: 3 sampai 5 proyek rapi yang menjawab masalah, cara kerja, cara menjalankan, dan hasil; jujur soal batas.
  • README adalah pintu depan: satu kalimat penjelasan, pemasangan, contoh pemakaian, tes, lisensi.
  • Periksa kebersihan repo: LICENSE, tes, .gitignore, dan tanpa rahasia; rahasia yang bocor harus dicabut, bukan hanya dihapus.
  • Open source: mulai dari proyek yang Anda pakai, baca LICENSE, README, CONTRIBUTING, dan Kode Etik; perbaikan kecil dulu; kontribusi tidak hanya kode.
  • Karier: data, GIS, web, AI, dan riset punya pintu masuk di buku ini; kemampuan dasar dan kebiasaan rekayasa dibutuhkan semua jalur.
  • Wawancara: pahami soal, uji kasus tepi, pilih struktur data, jelaskan kompleksitas.
  • Terus belajar: What’s New, PEP, blog resmi, dokumentasi pustaka, dan proyek kecil rutin.

Penutup Seri A5

Selamat! Anda telah menyelesaikan Seri A5, dan itu berarti Anda menamatkan seluruh Tingkat Advanced (Jilid 3) serta seluruh perjalanan buku ini. Di seri ini Anda belajar membuat kode yang mengatur kode (deskriptor, metaclass, AST), mengintip ruang mesin CPython (objek, referensi, bytecode, GIL, JIT, subinterpreter), mempercepat bagian kritis dengan kode native dan GPU, membagi pekerjaan ke banyak worker yang tahan gagal, dan membungkus semuanya sebagai portofolio yang bisa Anda tunjukkan kepada dunia.

Lihat jauh ke belakang: Anda mulai dari mengetik “Halo” di terminal. Sekarang Anda bisa mencatat data lapangan, membangun aplikasi web dan peta, melatih model deteksi pohon, membuat asisten AI yang membaca dokumen kehutanan, dan menjalankan semuanya terdistribusi. Kebun yang tadinya kosong sudah menjadi kebun besar. Ia tidak akan pernah “selesai”: musim berikutnya selalu ada tanaman baru, dan itu sebagian besar kenikmatannya.

Terima kasih telah menanam bersama sampai sini. Jaga kebiasaan yang sudah Anda bangun: ukur sebelum mengira, tulis tes, jaga rahasia, dan jujur tentang apa yang belum Anda ketahui.

Selanjutnya: bacalah Proyek Akhir (sistem informasi utuh dengan jalur fokus pilihan Anda) dan Lampiran (pemasangan, lembar contekan, glosarium, kunci jawaban, peta jalur belajar, dan sumber belajar lanjutan), yang disusun terpisah dari bab-bab ini. Selamat belajar, dan selamat berkarya.