There is a strange gap between “knowing Python” and “being able to use Python”. Many people watch dozens of videos, copy examples, and feel they understand — then get stuck when they have to write something from scratch. This book was made to close that gap.
The approach is simple: learn by running. Every example in this book can be run right in your browser, on the spot. You do not need to install Python, set up an editor, or wait for any process. Read, run, change, run again — and see for yourself what changes.
This book moves through three consecutive parts:
Every chapter follows the same pattern: a short, dense explanation, examples you can run, then exercises with solutions that you can open. Do not skip the exercises. Reading makes you familiar; writing and running is what makes you capable.
An honest note. Not everything can be run in the browser. Chapters that need files on your computer, packages from the internet, a network, or long-running programs will mark this clearly, and point you to the right environment. That is not a weakness — it is part of learning to know where something should be run.
Happy reading, and happy building.
— RWID
This is not an ordinary book: it has Python inside it. Every code example can be run right away, without installing anything.
The reader’s top bar has a Lab. Inside it is the Python Lab: a Python interpreter embedded in this book, where you can try code without leaving the page. For bigger projects, open the full IDE, a complete editor in its own window where you save and run your files.
Above every code block there are two buttons:
My advice. Don’t just press Run. Change the numbers first, swap the names, break it on purpose — then see what happens. Mistakes are the fastest teacher.
Python in the browser is real, but it lives inside a sandbox. It cannot touch files on your computer, install packages from the internet, or open a network connection. So some topics — honestly — cannot be run here. Such chapters mark it clearly:
Local environment needed. This cannot be run in the browser. Follow the guide, and run it in local Python + VS Code or Google Colab.
A full guide to installing Python locally is in Appendix C. In short:
| ✅ Works here | ⚠️ Limited here | ❌ Needs a local environment |
|---|---|---|
| Pure Python & basic stdlib | Large computations/sizes | Reading and writing files on your computer |
| NumPy, pandas, Matplotlib | No real network | pip install any package |
| scikit-learn (small scale) | Storage is not permanent | requests, sockets, databases |
HTML via rwid.show_html | GUI (tkinter/turtle), os/subprocess | |
multiprocessing, servers (Flask/FastAPI) |
Part I and one opening chapter of Part II can be read for free. To unlock the whole book — up to the final project — activate it with 25 using the button at the end of the last sample chapter, or from the Books / Store app.
Enjoy exploring. Start on the next page.
Click a title to jump to it. Chapters marked with a lock need to be unlocked ( 25).
Every journey begins with a single line. In Python, that line is print(). Let’s run the simplest one first, then dissect what actually happens.
print("Halo, dunia!")
One line, one command. print() is a function: it takes something inside the parentheses and displays it on the screen. Text enclosed in quotation marks — like "Halo, dunia!" — is called a string.
You can display more than one thing at once, separated by commas:
print("Nama saya", "Eko")
print("2 + 3 =", 2 + 3)
Notice: "Nama saya" and "Eko" are separated by a space automatically, while 2 + 3 is really calculated first into 5, and only then printed.
A line that starts with # is ignored by Python. We use it to explain why, not what.
# This is a comment: Python does not run it.
print("Halo") # a comment can also go at the end of a line
Good code speaks through its names; comments are for when the reason is not clear from the code itself.
Try running the code below. It is deliberately wrong, so that you get to know what an error looks like:
print("Halo"
Python will stop and report a SyntaxError. This is not a disaster — it is Python telling you that a parenthesis was left unclosed. Reading error messages is a core skill. Usually the last line of the message is the heart of it.
print("Halo")
Compare: one extra character, and everything runs.
Python reads a program from top to bottom. Each print() runs in order:
print("Satu")
print("Dua")
print("Tiga")
We will cover variables fully in the next chapter, but one small example here will help:
nama = "Eko"
tahun_lahir = 1990
print("Hai,", nama)
print("Usia pada 2026:", 2026 - tahun_lahir)
The = sign gives a name to a value. After nama = "Eko", wherever we write nama, Python replaces it with "Eko".
17 * 24.panjang = 8 and lebar = 5, then display the area of the rectangle.SyntaxError, run it, and read the error message. Then fix it.# 1
print("Eko")
print("Yogyakarta")
# 2
print(17 * 24)
# 3
panjang = 8
lebar = 5
print("Luas:", panjang * lebar)
# 4 — a common mistake: an unclosed parenthesis
# print("Halo"
print("Halo")
print() displays values on the screen.# starts a comment that Python ignores.In the next chapter we get properly acquainted with variables and data types.
A variable is how we give a name to something so it can be used again. Python does not require us to declare a type — it guesses it from the value — but understanding data types is still a must, because the type determines what can and cannot be done.
umur = 25
nama = "Siti"
tinggi = 1.68
menikah = False
Four lines, four basic types: int (25), str ("Siti"), float (1.68), and bool (False). To see the type of something, use type():
print(type(25)) # <class 'int'>
print(type(1.68)) # <class 'float'>
print(type("Siti")) # <class 'str'>
print(type(False)) # <class 'bool'>
int is a whole number; float is a number with a decimal point. Division always produces a float:
print(10 / 3) # 3.3333333333333335
print(10 // 3) # 3 (floor division)
print(10 % 3) # 1 (remainder)
print(2 ** 10) # 1024 (power)
The operators // and % are everyday companions: one divides evenly, the other gives the remainder. Together, they can break a number into parts:
menit = 145
print(menit // 60, "jam", menit % 60, "menit") # 2 jam 25 menit
Strings can be joined with + and repeated with *:
depan = "Eko"
belakang = "Wibowo"
print(depan + " " + belakang)
print("ha" * 3) # hahaha
print(len("Python")) # 6
We will dig deeper into strings in Chapter 7. For now, just remember that a string is a sequence of characters, and len() counts its length.
bool has only two values: True and False. These values come out of comparisons:
print(5 > 3) # True
print(5 == 5) # True (note: == is for comparing, = is for assigning)
print(5 != 5) # False
A classic trap.
=assigns a variable;==compares. Mixing up this one sign is one of the most common mistakes for beginners.
Sometimes we need to change a type. The functions int(), float(), and str() do it:
nomor = "42" # this is a string, not a number
print(nomor + "5") # 425 (it sticks together, not adds!)
print(int(nomor) + 5) # 47 (now it is really added)
print(str(100) + "!") # 100!
print(int(3.9)) # 3 (truncated, not rounded)
The most convenient way to print mixed values is the f-string — a string prefixed with f that can hold expressions inside {}:
nama = "Eko"
umur = 36
print(f"Hai {nama}, usiamu {umur} tahun.")
print(f"Setahun lagi: {umur + 1}")
print(f"Pi sekitar {3.14159:.2f}") # 2 digits after the decimal point
f-strings will keep appearing throughout this book. Master them starting now.
Sometimes a variable does not have a value yet. In Python, “not there yet” is represented by None:
hasil = None
print(hasil) # None
print(hasil is None) # True
None is different from 0, and different from "". It truly means “nothing”.
200 minutes."7" and 3; add them as numbers, then display the result.berat = 72.5 (kg) and tinggi = 1.75 (m), then calculate the body mass index berat / tinggi ** 2 and display it with 1 digit after the decimal point.# 1
depan = "Eko"
belakang = "Wibowo"
tahun = 1990
print(f"{depan} {belakang}, lahir {tahun}.")
# 2
total = 200
print(f"{total // 60} jam {total % 60} menit")
# 3
print(int("7") + 3)
# 4
berat = 72.5
tinggi = 1.75
imt = berat / tinggi ** 2
print(f"IMT: {imt:.1f}")
int, float, str, bool, and None.// divides as a whole number, % takes the remainder, ** raises to a power.= assigns, == compares.Why does good Python code feel concise and pleasant to read? Because it uses idioms — ways of writing that are common among Pythonistas. This chapter teaches comprehensions and a number of habits that make code shorter, clearer, and more Pythonic.
The old way of filling a list:
kuadrat = []
for x in range(1, 6):
kuadrat.append(x ** 2)
print(kuadrat)
A comprehension condenses it into one line:
kuadrat = [x ** 2 for x in range(1, 6)]
print(kuadrat) # [1, 4, 9, 16, 25]
genap = [x for x in range(10) if x % 2 == 0]
print(genap) # [0, 2, 4, 6, 8]
The pattern: [expression for item in iterable], optionally filtered with if.
For a dict, use {key: value for ...}; for a set, {...}:
panjang = {kota: len(kota) for kota in ["jakarta", "bali", "medan"]}
print(panjang)
unik = {huruf.lower() for huruf in "Halo Dunia" if huruf != " "}
print(sorted(unik))
enumerate gives sequence numbers; zip walks over two lists at once:
buah = ["apel", "mangga", "jeruk"]
for nomor, nama in enumerate(buah, start=1):
print(f"{nomor}. {nama}")
nama = ["Eko", "Siti"]
umur = [36, 25]
for n, u in zip(nama, umur):
print(f"{n} berusia {u} tahun")
Both return iterators, so they are memory-friendly. zip stops at the shortest list.
A simple condition can be written on one line; unpacking breaks a sequence apart into several variables:
umur = 20
print("dewasa" if umur >= 18 else "anak")
a, b = 1, 2
a, b = b, a # swap without a helper variable
print(a, b)
kepala, *ekor = [1, 2, 3, 4]
print(kepala, ekor) # 1 [2, 3, 4]
f-strings can control number formatting and alignment:
nilai = 1234567.891
print(f"{nilai:,.2f}") # 1,234,567.89
print(f"{0.87:.1%}") # 87.0%
print(f"{42:05d}") # 00042
print(f"{'kanan':>10}|")
print(f"{'kiri':<10}|")
The walrus operator := assigns a value while testing it:
data = [1, 2, 3, 4, 5, 6]
if (n := len(data)) > 3:
print(f"ada {n} item")
from collections import Counter
kata = "susu roti susu teh roti susu".split()
print(Counter(kata).most_common(2))
pengguna = {"nama": "Eko"}
print(pengguna.get("kota", "tidak diketahui"))
harga = {"beras": 12000, "gula": 15000, "minyak": 18000}, build a new dict containing the prices after a 10% discount.zip + a dict comprehension to pair ["a", "b", "c"] with [1, 2, 3].["Nasi Goreng", "Mie Ayam", "Sate"] using enumerate.hasil = []
for x in range(1, 11):
if x % 3 == 0:
hasil.append(x * x)
# 1
print([x ** 2 for x in range(1, 11) if x % 2 == 1])
# 2
harga = {"beras": 12000, "gula": 15000, "minyak": 18000}
print({nama: int(bayar * 0.9) for nama, bayar in harga.items()})
# 3
kunci = ["a", "b", "c"]
nilai = [1, 2, 3]
print({k: v for k, v in zip(kunci, nilai)})
# 4
for nomor, item in enumerate(["Nasi Goreng", "Mie Ayam", "Sate"], start=1):
print(f"{nomor}. {item}")
# 5
print([x * x for x in range(1, 11) if x % 3 == 0])
enumerate adds numbering; zip walks over several sequences at once.a if condition else b for short conditions.* collects the rest.:= assigns while testing.In the next chapter we split programs into modules and packages that can be imported.