Part 1 · Foundations · Module 01

First Steps

What actually happens when you "run Python"? In this module you will find out, from the text you type to the bytecode the interpreter executes. Along the way you will learn the first tools every Python programmer uses daily: print, comments, the REPL, and the art of reading an error message.

⏱ ~75 minutesPrerequisites: M00

What is a program?

A program is a precise list of instructions for a computer. "Precise" is the key word. A human reading a recipe that says "add a pinch of salt" fills in the gaps. A computer cannot fill gaps: it does exactly what the instructions say, nothing more and nothing less. Programming is the craft of writing instructions so clear that a machine with no common sense can follow them.

Instructions are written in a programming language, a language with strict rules of grammar (called syntax) and meaning (called semantics). Python is a programming language designed to be readable: Python code often looks almost like English.

temperature = 31
if temperature > 30:
    print("It's hot. Drink water!")

Even before learning any rules you can probably guess what this does. That readability is not an accident; it is Python's central design goal, and it is a big reason Python is used for everything from scientific research to websites to machine learning.

The text of a program is called source code (or just "code"). Python source code is stored in plain text files ending in .py.

Remember: a program is an exact list of instructions; syntax is the grammar, semantics is the meaning; source code is the text you write.

How Python runs your code

Your CPU (the computer's processor) does not understand Python. It understands only machine code, very low-level numeric instructions. Something has to bridge the gap. For Python that something is the interpreter: a program that reads your Python code and carries out its instructions. The standard interpreter, the one Pixi installs, is called CPython because it is written in the C language.

CPython works in two stages:

flowchart LR
  A["Source code
hello.py"] -->|"compile"| B["Bytecode
(instructions for the PVM)"] B -->|"execute"| C["Python Virtual Machine
(the evaluation loop)"] C --> D["Output, files,
network..."]
  1. Compile to bytecode. CPython first checks your code's syntax and translates it into bytecode: a compact list of simple instructions such as "load this name", "multiply", "store the result". If there is a SyntaxError this stage fails and nothing runs.
  2. Execute on the PVM. The Python Virtual Machine (PVM) is a loop inside CPython that executes bytecode instructions one after another. It is "virtual" because it is a machine made of software rather than hardware.

You can peek at the bytecode with the standard-library dis module ("disassembler"). Do not try to memorize it; just notice that one line of Python becomes a few tiny steps.

Reading the output: LOAD_NAME price fetches the value named price, LOAD_SMALL_INT 2 pushes the number 2, BINARY_OP (*) multiplies them, and STORE_NAME total saves the result under the name total. The PVM keeps intermediate values on a stack, a pile where the last thing put on is the first taken off.

Remember: CPython compiles source to bytecode, then the PVM executes the bytecode. Syntax errors stop the first stage, so they prevent the whole file from running.

The REPL vs scripts

You met both in M00. Here is when to use each.

REPL: pixi run python

  • Interactive: type a line, see the result at once
  • Shows the value of every expression automatically
  • Great for experiments, checking a fact, exploring an object
  • Forgets everything when you exit

Script: pixi run python app.py

  • Runs a whole file top to bottom
  • Shows only what you print
  • For programs you keep, share, and run again
  • Can be edited in a proper editor and tracked with git

The biggest beginner surprise: in the REPL, typing 2 + 2 displays 4. In a script, the same line computes 4 and then silently throws it away. If you want to see it, you must print it.

>>> 2 + 2        # REPL: the value is echoed
4
>>> "hi".upper()
'HI'

The browser cells in this course behave like scripts. Predict what this cell shows:

Remember: the REPL echoes expression values; scripts only show what you print.

Talking to the world with print

print is a function: a named, reusable piece of code that you call by writing its name followed by parentheses. Values inside the parentheses are arguments, the inputs you hand to the function. print writes its arguments to the screen (more precisely, to standard output, the program's main text output stream).

print("Hello")            # one argument: a string
print("Answer:", 42)      # two arguments, separated by a comma
print()                   # no arguments: prints an empty line

A string is a piece of text in quotes. Single ('hi') and double ("hi") quotes mean the same thing.

sep and end

When you give print several arguments it puts a separator between them (a space by default) and finishes with an end string (a newline by default, written "\n"). You can change both with keyword arguments: arguments passed by name, as in sep="-".

Remember: print(a, b, sep=" ", end="\n"); arguments are separated by sep and followed by end.

Comments, expressions, and statements

Comments

A comment starts with # and runs to the end of the line. Python ignores it completely; it is a note for humans, including future you.

# Convert minutes to hours for the timesheet report.
minutes = 135
hours = minutes / 60  # 2.25

Good comments explain why, not what. x = x + 1 # add one to x wastes the reader's time; retries = retries + 1 # the API sometimes fails on the first call tells them something the code cannot.

Expressions

An expression is a piece of code that produces a value. 42, "hi", 3 * 7, minutes / 60, and len("Pixi") are all expressions. You can combine expressions into bigger ones, like LEGO bricks.

Statements

A statement is a complete instruction that does something. An assignment statement such as hours = minutes / 60 evaluates the expression on the right and gives the result a name (also called a variable) on the left. if, for, and import are statements too. A statement does not itself have a value: you cannot write print(x = 5) and expect the assignment to happen.

CodeKindWhy
7 * 6ExpressionProduces the value 42
answer = 7 * 6StatementAssignment: names the value
print(answer)BothA call is an expression (it returns None); used alone on a line it is an expression statement
import mathStatementLoads a module; has no value

Step through this program with the tracer. Watch each statement run in order and each name appear with its value.

Remember: expressions produce values; statements perform actions; assignment binds a name to the value of an expression.

Indentation is part of the grammar

Many languages use braces { } to group lines into a block (a group of statements that belong together). Python uses indentation, the spaces at the start of a line. A line ending with a colon : introduces a block, and every line of the block is indented by the same amount. The standard is four spaces.

score = 87
if score >= 50:
    print("You passed!")       # inside the if block
    print("Well done.")        # still inside
print("Thanks for playing.")   # back outside: always runs

Because indentation carries meaning, code that is visually tidy is also code that is correct. The flip side is that inconsistent indentation is an error:

  File "app.py", line 3
    print(x)
    ^^^^^
IndentationError: expected an indented block after 'if' statement on line 2

Remember: a colon opens a block; the block is the indented lines below it; use four spaces.

Reading tracebacks like a detective

Errors come in two families. Syntax errors are found while compiling, before any code runs. Runtime errors, called exceptions, happen while the program is running, when an instruction turns out to be impossible. Here is a runtime error:

Traceback (most recent call last):
  File "receipt.py", line 2, in <module>
    print("Total: " + 5)
          ~~~~~~~~~~^~~
TypeError: can only concatenate str (not "int") to str

Detective method:

  1. Last line: what happened. A TypeError: the types (kinds) of value do not fit. You cannot glue (concatenate) a string and an integer with +.
  2. Above it: where. File receipt.py, line 2. The tildes and caret point at the +.
  3. Form a hypothesis and test it. "I need to turn 5 into text": "Total: " + str(5), or just print("Total:", 5).

Python 3.14 is exceptionally helpful with suggestions. Run each line separately (comment the others out with #) and read the hints:

Remember: syntax errors stop everything; exceptions stop at the failing line; the last line of a traceback says what, the lines above say where.

Exploring with type(), dir(), and help()

Everything you work with in Python is an object: a value in memory that has a type (what kind of thing it is) and operations it supports. Three built-in functions let you explore any object, and you will use them for the rest of your career:

Names beginning with underscores (like __len__) are special internal names; filtering them out keeps the list readable. You will learn what they do in the module on the data model.

Remember: type answers "what is it?", dir answers "what can it do?", help answers "how do I use it?".

Style: PEP 8 and the Zen of Python

Code is read far more often than it is written. Python's community agreed on a style guide called PEP 8 (a PEP, "Python Enhancement Proposal", is a design document for Python). Its core rules:

X=10;Y=20
TOTALPRICE=X*Y
print( TOTALPRICE )
quantity = 10
unit_price = 20
total_price = quantity * unit_price
print(total_price)

Python also has a philosophy, written as a poem by Tim Peters and hidden as an "Easter egg" in the language:

Lines like "Readability counts", "Explicit is better than implicit", and "Errors should never pass silently" will come up again and again in this course. They are good guides when you have to choose between two ways of writing something.

Practice

Use one print call with three arguments, 2026, 10, and 14, and a sep so that it prints exactly 2026-10-14.

Hint

Add sep="-" as a fourth argument.

Show solution
print(2026, 10, 14, sep="-")

Keep the two print calls, but change the first one with end so the program prints exactly one line: Ready, set, go!

Hint

By default end is a newline. Make it a single space.

Show solution
print("Ready, set,", end=" ")
print("go!")

This program has three bugs: an indentation problem, a typo in a name, and a string glued to a number. Fix them so it prints exactly two lines: Item: coffee and Price: 4.

Hint

Fix one error at a time, re-running after each. For the price, either use str(price) or pass two arguments to print.

Show solution
item = "coffee"
price = 4
print("Item: " + item)
print("Price:", price)

Assign to seconds_in_week an expression that computes the number of seconds in a week (60 seconds × 60 minutes × 24 hours × 7 days). Don't type the answer directly; let Python compute it. Then print the variable.

Hint

Multiplication is *: 60 * 60 * ...

Show solution
seconds_in_week = 60 * 60 * 24 * 7
print(seconds_in_week)

Print this three-line banner exactly. Try to build the border lines with string repetition ("-" * 8) instead of typing every dash.

+--------+
| Python |
+--------+
Hint

The middle line is "| Python |": 8 characters between the bars, matching 8 dashes.

Show solution
border = "+" + "-" * 8 + "+"
print(border)
print("| Python |")
print(border)

Mini-project: a personal greeting card

Mini-projectPersonal greeting card

Write a script that prints a decorated greeting card for someone you know. You will practise print, sep, end, string repetition, comments, and running a script with Pixi.

Steps

  1. In your practice workspace from M00, create card.py.
  2. At the top, write a comment saying what the script does and who it is for.
  3. Store the recipient's name, the occasion, and your name in variables.
  4. Print a border, a few lines of message, and a signature. Example output:
    **************************
    *   Happy birthday, Sam!  *
    **************************
    Wishing you a year full of
    good code and few bugs.
              -- from Ada
  5. Run it with pixi run python card.py, then add a task: pixi task add card "python card.py".
  6. Format it: pixi add ruff and pixi run ruff format card.py.

Acceptance criteria

  • The file starts with a comment explaining its purpose
  • Names, occasion, and sender are stored in variables with snake_case names
  • Borders are built with string repetition, not typed by hand
  • At least one print uses sep and at least one uses end
  • pixi run card prints the card without errors
  • You introduced a deliberate bug, read the traceback, and fixed it

Stretch goals

  • Make the border width match the length of the greeting using len().
  • Use dis.dis on one line of your card and identify the STORE_NAME instructions.
  • Ask for the recipient's name with input("Name? ") (you will study input in M02).

Quiz

Recap

Going further