Before this lesson

This is the starting point for this language; web development is not a prerequisite.

What you will be able to do

Run a first script and distinguish bindings, strings and numbers.

Understand the mechanism

A Python script is executed by an interpreter, not by placing it in a web page. Confirm the interpreter version in a terminal. Editors help write code but do not determine runtime identity automatically. Preserve filenames and line numbers when diagnosing errors.

Names bind to objects and assignment is not a mathematical equality. Integers, floats and strings support different operations. Conversion from external text can fail; later lessons handle that failure explicitly.

Indentation defines blocks, so keep it consistent. print produces output and f-strings embed values. Execution order matters: a later output sees the current binding rather than an earlier value.

Start with constants before adding interactive input so type behavior is separate from waiting for input. input returns text. Use explicit conversion rather than evaluating arbitrary input as code.

Runnable example

Use Python 3.11 or later. Save lesson.py in a separate practice directory and run python3 lesson.py, or py lesson.py on Windows. Examples use only the standard library.

name = "Honeysuck"
minutes = 25
sessions = 3
raw = "4"
print(f"{name}: {minutes * sessions} minutes")
print(type(raw).__name__, type(sessions).__name__)
print(int(raw) + sessions)
print(7 / 2, 7 // 2, 7 % 2)

Trace and verify

Expect 75 minutes, str int, seven, then 3.5, 3 and 1. Changing raw to 4.5 makes integer conversion fail; the failure belongs to conversion, not output. Zero sessions should produce zero duration normally.

Common mistakes and boundaries

Floor division is not truncation toward zero for negative numbers. Floating-point values are approximate. Avoid shadowing built-ins such as print and list with unrelated variables.

Practice challenge

Output total minutes plus whole hours and remaining minutes. Test zero, 59, 60 and 125.

Reference solution and reasoning

Use floor division and remainder, predict all four results and compare. Later separate validation from formatting into independent functions.

Lab: names, objects and shallow copies

Why can editing a copied list still change the original? The copy duplicates the outer container, not every object reachable through it. Draw the references before running this self-contained lesson.py with Python 3.11 or later.

original = [["HTML"], ["CSS"]]
alias = original
shallow = original.copy()
shallow[0].append("forms")
shallow.append(["JavaScript"])
print(original)
print(len(original), len(shallow))
print(alias is original, shallow is original)
assert original[0] is shallow[0]
independent = [row.copy() for row in original]
independent[0].append("tables")
assert "tables" not in original[0]

Expected observations

Output is the Python representation of [["HTML", "forms"], ["CSS"]], then 2 3, then True False. Python normally displays these strings with single quotes; the values are the same.

Why this happens and where it stops applying

alias and original name the same outer object. shallow is a new outer list whose first item still points to the same inner list. Appending forms changes that shared inner object, whereas appending a row changes only shallow. Copying each inner list is sufficient for this two-level example, not for arbitrary object graphs. Deep copying also does not define meaningful duplication for every external resource; decide which state must be independent first.

Extension challenge

Start with [[]] * 3 and append 1 to row zero. Predict all three rows, then create genuinely independent rows.

Reasoned solution

All three rows show [1] because multiplication repeats references to one inner list. Use [[] for _ in range(3)] to construct a new list per iteration. Checking rows[0] is rows[1] reveals the relationship that equality between initially empty lists would hide.

Further reading