Lesson 01 · 8 min read · Python for placements

How Python actually runs your code

Source to bytecode to the interpreter loop, why Python compiles yet is called interpreted, and the one mental model that explains the rest of the language.

You can write Python for two years without knowing what happens when you press run. You cannot get through a technical round that way, because the first follow-up to "what language are you comfortable in?" is usually "and what happens when you run a Python file?"

The three steps

When you run python app.py, three things happen in order.

1. Your source is compiled to bytecode. Python reads app.py and turns it into a compact instruction set — not machine code for your CPU, but instructions for a machine that does not exist physically. You can see them:

import dis

def add(a, b):
    return a + b

dis.dis(add)
  2           0 LOAD_FAST                0 (a)
              2 LOAD_FAST                1 (b)
              4 BINARY_OP                0 (+)
              8 RETURN_VALUE

That is your function. Load the first argument, load the second, add them, return.

2. The bytecode is cached. For imported modules, Python writes the result into a __pycache__ folder as a .pyc file, so the next run skips the compile step. The file you ran directly is not cached — only the modules it imports. This is why a __pycache__ folder appears next to your imports and never next to your entry point.

3. The interpreter executes it. A loop inside CPython reads one bytecode instruction at a time and does what it says. That loop is written in C. When people say "Python is slow", they mean this: a C program's addition is one CPU instruction, and Python's addition is a trip through the interpreter loop, a type check, and a function call.

So is Python compiled or interpreted?

Both, and the honest answer is the one that gets you marks: Python compiles to bytecode, and that bytecode is interpreted. It is not compiled to machine code the way C is, and it does not skip compilation the way a shell script does.

The distinction people are really reaching for is when errors show up. A syntax error is caught at compile time, before a single line runs:

print("this never prints")
def broken(:
    pass

Nothing prints. The file failed to compile. But a name error is a runtime error — the compiler is happy, and the failure waits for execution to reach it:

print("this does print")
print(undefined_name)   # NameError, only when this line runs

That difference is worth understanding because it explains a class of bug that confuses beginners: code that "worked yesterday" and now fails on line 200 was never checked past line 1.

CPython, and the others

CPython is the reference implementation, written in C, and it is what you get from python.org. When someone says "Python", they almost always mean CPython. Worth knowing that alternatives exist and roughly why:

Implementation Written in Why it exists
CPython C The reference. What you are using.
PyPy Python A JIT compiler — often several times faster on long-running code
Jython Java Runs on the JVM, can call Java libraries
MicroPython C Fits on a microcontroller

You will not be asked to use them. You may well be asked whether you know they exist.

The one mental model to carry forward

Here is the idea that makes half of this course obvious in advance.

A Python variable is not a box. It is a label.

In C, int x = 5 reserves memory and puts 5 in it. x is that memory. In Python, x = 5 creates an object with the value 5 somewhere in memory, and makes the name x point at it. The name is a label tied to an object, not a container holding a value.

a = [1, 2, 3]
b = a          # not a copy — a second label on the SAME list
b.append(4)
print(a)       # [1, 2, 3, 4]

a changed because there was only ever one list. Two labels, one object.

You can watch this directly. id() gives the identity of an object:

a = [1, 2, 3]
b = a
c = [1, 2, 3]

print(id(a) == id(b))   # True  — same object
print(id(a) == id(c))   # False — different objects
print(a == c)           # True  — equal contents

That last block is the entire difference between is and ==, which lesson 2 covers properly. is asks are these the same object. == asks do these have the same value.

Nearly every confusing Python behaviour you will meet — why a function can modify the list you passed it, why copying a list needs [:], why a mutable default argument is a trap, why two identical strings can be the same object — is this one model applied in a new place.

What to take into an interview

  • Python compiles to bytecode; the bytecode is then interpreted by a loop written in C.
  • .pyc files in __pycache__ are cached bytecode for imported modules, not machine code.
  • Syntax errors are caught before execution; name and type errors are caught during it.
  • CPython is the reference implementation. PyPy is the fast one, with a JIT.
  • A variable is a name bound to an object. Assignment binds a name; it never copies a value.

Say that last point out loud once. It is the sentence that most freshers cannot produce, and the one that most reliably makes an interviewer sit up.

Lesson 1 of 12 · all 12 are free to read, no account. Course contents