← All 45 books Python, one concept per page Get the full edition · £10
One concept per page

Python, one concept per page

The twenty-five ideas that take you from never coded to running real programs.


Steve Hodgkiss 8 concepts

A diagram, the classic mistake, and two lines to type. That's a page.

Python, one concept per page

The twenty-five ideas that take you from never coded to running real programs.


Set in Space Grotesk, Inter and JetBrains Mono (SIL Open Font License).

Language behaviour verified against the official Python documentation: docs.python.org/3 (tutorial and library reference).

Python and the Python logo are trademarks of the Python Software Foundation. This book is an independent guide and is not affiliated with or endorsed by the PSF.

Your purchase is for personal use only. You do not have redistribution rights: please do not share, resell, or republish this book or its pages.

© 2026 Steve Hodgkiss. All rights reserved. Personal use only; no redistribution rights.

Edition 1.0 · stevehodgkiss.net

Contents

Contents


Part 1 · First steps4
print5
Variables6
input7
Part 2 · Collections8
Lists9
in and for10
Part 3 · Flow
if elif else11
Part 4 · Real programs12
Reading a file13
try and except14
Part 1 of 4
Talking to the machine
1

First steps

The five moves behind every first program: say something, remember something, ask, tell apart, and join text.


In this part
  1. 01print
  2. 02Variables
  3. 03input

print() turns what you give it into text, joins the pieces with spaces, and writes them to the screen followed by a newline. It is the fastest feedback loop in programming.

Python · No. 01
First steps

print

Say something to the screen

YOU TYPE A LINE. PYTHON ANSWERS.terminalprint("Hello, world!") print("Python 3.14")runs> Hello, world!> Python 3.14new line each timeprint() takes what you list, turns each into text, joins with spaces, adds the newline.Commas make it one call: print("Total:", 49) prints Total: 49

Every session starts here. You type a line, press Enter, and the answer appears immediately. No compile step, no ceremony. That instant reply is what makes Python a good place to learn: you can check every idea as soon as you have it.

The classic confusion: print("2" + "3") prints 23, not 5. Both were text, and + joins text. Nothing is broken; the machine did exactly what was asked.

Numbers to add, quotes to join. Print either kind.

If you can see what your program is thinking, you can fix it. print is how you look.

TRY IT NOW

print("Hello, world!") print("Total:", 2 + 3)

The = sign attaches a name to a value so you can use it later. It is a label pointing at a box, not a statement that two things are equal.

Python · No. 02
First steps

Variables

A label you stick on a value

AN ASSIGNMENT IS A LABEL ON A BOX, NOT A MATHS EQUATIONpricethe name=points4.50pricere-pointprice = 99priceold value goneReading the name later fetches whatever the label points at now.

School maths taught you = means equal, so x = x + 1 looks impossible. In Python it reads right to left: work out the right side, then point the name at the result. The old value is simply left behind.

Give things names that say what they mean: total_cost beats tc. The name is for the next person who reads the code, and that person is usually you, three weeks later.

name = value is the whole grammar. You will type it ten thousand times.

Names are labels you move. Values are what they point at.

TRY IT NOW

price = 4.50 price = price + 1 print(price) # 5.5

input() pauses the program, shows its prompt, reads one line of typing, and returns it as a string, newline stripped. Numbers you type arrive as text until you convert them.

Python · No. 03
First steps

input

Ask the person at the keyboard

EVERYTHING TYPED AT input() COMES BACK AS TEXTyour programname = input("Name? ")asksyou type42a number, surely"42"still a stringinput() returns a string, quotes or not. Convert on purpose when you need a number:age = int(input("Age? ")) # now arithmetic works

Programs get interesting the moment they respond to a person. input() shows its prompt, waits for a line, and hands it back as text, exactly as typed.

The classic crash comes one line later: age = input() then age + 1 explodes with TypeError, because "30" is a string and Python refuses to guess.

Convert at the door, where the intent is obvious: int() for whole numbers, float() for decimals.

input hands you text. Say out loud what you actually want, and convert there.

TRY IT NOW

name = input("Name? ") age = int(input("Age? ")) print("Hi", name, "- next year:", age + 1)

Part 2 of 4
Keeping many things
2

Collections

Real programs juggle lists of things. These five ideas cover almost all of it.


In this part
  1. 01Lists
  2. 02in and for

A list is an ordered sequence written in square brackets. Positions are numbered starting at 0, square brackets read one position, and negative indexes count from the end. Lists are mutable: you can change what a slot holds.

Python · No. 04
Collections

Lists

Many values in one named row

A LIST IS A ROW OF SLOTS, NUMBERED FROM ZERO012345index"cat""dog""owl""fox""hen""pig"petspets[1][-1] is the last slotSix items live in slots 0 to 5. len(pets) is 6, pets[5] is the last.

One variable per thing stops scaling at about three things. A list holds any number of values in one name, keeps them in order, and gives each a numbered slot.

The number that trips everyone: counting starts at 0, so the first item is pets[0] and a six-item list ends at pets[5]. Ask for pets[6] and Python answers IndexError, not a polite nothing.

Negative indexes are the friendly shortcut: pets[-1] is always the last item, however long the list grew.

Six things, slots zero to five. The fencepost is the whole trick.

TRY IT NOW

pets = ["cat", "dog", "owl", "fox"] print(pets[0], pets[-1], len(pets))

The for loop visits each item of any sequence in order, handing it to you under a name you choose. The in operator asks whether a value is anywhere in a collection and answers True or False.

Python · No. 05
Collections

in and for

Ask membership, then walk the row

for WALKS THE ROW. in ASKS ONE QUESTION FIRST.catdogowlfoxhen2pet = "dog" (this pass)visited"owl" in pets-> TrueNo counters, no slot numbers. for pet in pets: visits each item once, left to right, then stops.for k, v in person.items(): walks a dictionary the same way.

Here is the loop you will write most: for pet in pets: and an indented line that runs once per item. Python hands you each value in order, under the name you invented.

Habits carried over from other languages: you almost never need for i in range(len(pets)) just to read items. If you only need the values, walk the values.

Before the loop, in does the quick check: if "owl" in pets: Dictionaries join in with for k, v in d.items():

TRY IT NOW

pets = ["cat", "dog", "owl"] print("owl" in pets) for pet in pets: print(pet.upper())

An if chain tests each condition from the top and runs only the first true branch; else is the optional catch-all. elif is short for else if. Comparisons use ==, assignment uses =.

Python · No. 06
Flow

if elif else

The program picks a path

PYTHONTON CHECKS EACH TEST TOP TO BOTTOM, THEN RUNS THE FIRST TRUE ONEscorescore >= 70 ?True: take this branch and stopscore >= 50 ?False: fall throughelseno test: the catch-allgradeone onlyIn a test, = is a syntax error. == asks "are these equal?"if score = 70: # SyntaxError if score == 70: # correct

This is where a program stops being a receipt and starts making decisions. Each test is checked top to bottom; the first true one runs and the rest are skipped. Order is therefore meaning.

Grammar note, not maths note: one = stores, two == compares. Writing if score = 70: is a SyntaxError, and it is the single most common typo in the language.

Chain with elif when categories exclude each other; let else catch the rest. First true test wins.

TRY IT NOW

score = 72 if score >= 70: print("pass") elif score >= 50: print("borderline") else: print("fail")

Part 4 of 4
Code that touches the world
4

Real programs

Files, failures, other people's code, and a safe place to install it all.


In this part
  1. 01Reading a file
  2. 02try and except

open(filename) returns a file object you can read from: the whole file, one line, or line by line in a for loop. A with block closes the file automatically when the block ends, even on an error.

Python · No. 07
Real programs

Reading a file

Bring the outside world in

ONE OPEN, THREE MOVES, ONE CLOSEnotes.txton diskopenf.read() whole filef.readline() one linefor line in f: eachPath(...).read_text()pick onewith open(...) as f:closes it for you,even if the runcrashes halfwayText mode gives you strings; each line keeps its trailing \n until you strip it.

Everything interesting eventually lives in a file: spreadsheet exports, logs, a novel. open it, pick how much to read, and let with close it behind you.

The fuss that follows every first attempt: lines arrive with an invisible \n on the end, so "cat" and "cat\n" never match. It looks like a ghost bug.

line.strip() trims the ends before you compare, and the with line means you never leak a half-open file again.

Open, read, close. The with line makes the close automatic.

TRY IT NOW

with open("notes.txt") as f: for line in f: print(line.strip())

If a statement in a try block raises an exception, the rest of the block is skipped and the matching except clause runs instead; execution then continues after the try/except. Unmatched exceptions still stop the program.

Python · No. 08
Real programs

try and except

The safety net under risky lines

A SAFETY NET UNDER THE RISKY LINEStry:x = int(input())the risky lineValueError"not a number"except ValueError:the catch: say it, ask againprogram carries onCatch the specific error you expect. A bare except: hides every bug, including yours.

Someday a user will type "seven" where a number goes. try wraps the line that can fail; except is the planned response, and the program keeps running with its dignity intact.

The well-meant version that backfires: a bare except:, which also swallows your own typos and logic bugs as silent None-shaped mysteries.

Name the error you expect: except ValueError:, so the surprises still surface loudly. The classic loop asks until the answer parses.

Errors are not failure. An unhandled one is.

TRY IT NOW

try: age = int(input("Age? ")) print("Next year:", age + 1) except ValueError: print("That was not a number.")

Index

Index


if elif else11
in and for10
input7
Lists9
print5
Reading a file13
try and except14
Variables6