CD Notes
Deep exploration of Python compilation, bytecode, virtual machine, and execution model
Python's implementation (CPython) provides fascinating insights into interpreter design. Understanding how Python code executes helps optimize performance.
Python Execution Model
Python Bytecode Example
Python Code:
def add(a, b):
return a + b
result = add(5, 3)
print(result)Python Bytecode (disassembled):
Bytecode Instructions
Python uses stack-based bytecode with around 120 different instructions:
| Instruction | Meaning |
|---|---|
| LOAD_CONST | Load constant value onto stack |
| LOAD_NAME | Load variable value onto stack |
| STORE_NAME | Store stack top to variable |
| BINARY_ADD | Pop two values, add, push result |
| CALL_FUNCTION | Call function with args |
| RETURN_VALUE | Return from function |
| JUMP_ABSOLUTE | Jump to instruction |
| POP_JUMP_IF_FALSE | Pop and jump if false |
| BUILD_LIST | Build list from stack items |
CPython Compilation Process
Python Virtual Machine (PVM)
The Python Virtual Machine is a stack-based interpreter:
| TOS (Top) | ||
|---|---|---|
| TOS1 | ||
| TOS2 | ||
| ... |
Method Resolution Order (MRO)
Python uses C3 Linearization for MRO in multiple inheritance:
class A: pass
class B(A): pass
class C(A): pass
class D(B, C): pass
MRO of D: D → B → C → A → objectLinear order is calculated during class definition.
Scope and Namespace Management
Scope Resolution (LEGB Rule):
Python Object Model
Every Python object has:
// CPython PyObject structure
typedef struct {
Py_ssize_t ob_refcnt; // Reference count
PyTypeObject *ob_type; // Type (class)
} PyObject;Object Example:
x = 42| │ ob_refcnt | 2 │ (referenced twice) |
| │ ob_type | int │ (type is integer) |
| │ ob_value | 42 │ (actual value) |
Garbage Collection
Python uses reference counting + cycle detection:
Reference Counting
Object A ← referenced by 2 things
ob_refcnt = 2
When references drop to 0
Memory freed immediately
Cyclic References (Cycle Collection)
A ← B ← C ← A (cycle)
Reference counts never reach 0
Periodic garbage collector detects cycles
Frees circular references
Code Objects and Functions
def add(a, b):
return a + bCompiled to Code Object:
Function object wraps code object:
Bytecode Optimization Levels
python script.py # No .pyc cache
python -O script.py # Optimize, remove __doc__
python -OO script.py # Remove __doc__ and assertionsPerformance: CPython vs PyPy
CPython (standard)
Interpreted bytecode
Slower but straightforward
PyPy (alternative)
JIT compilation
3-10x faster
Warm-up time needed
Interview Q&A
Q: How does Python execute code? A: Python parses source code to an AST, compiles to bytecode, and the Python Virtual Machine interprets bytecode instructions using a stack-based model.
Q: What is bytecode in Python? A: Bytecode is a low-level instruction set that Python compiles source code into. It's stored in .pyc files and interpreted by the Python VM.
Q: How does Python manage memory? A: Python uses reference counting to track object references. When count reaches zero, memory is freed. A periodic garbage collector detects and frees cyclic references.
Q: What is the LEGB rule? A: LEGB defines the scope lookup order: Local, Enclosing, Global, Built-in. When resolving a variable name, Python searches in this order.
Q: Why is PyPy faster than CPython? A: PyPy uses JIT compilation, dynamically compiling hot bytecode to native machine code. CPython interprets every bytecode instruction, which is slower.
Exam Focus
Revise definitions, diagrams, examples, and short-answer points for Python Interpreter Architecture.
Interview Use
Prepare one clear explanation, one practical example, and one common mistake for this Compiler Design topic.
Search Terms
compiler-design, compiler design, compiler, design, modern, technologies, python, interpreter
Related Compiler Design Topics