Python 3.14 ·
✓ verified by execution on 2026-07-31
Welcome to the Expert level!
Python is often described as an interpreted language, but that’s only half the story. Before CPython executes your code, it translates your human-readable .py source text into a dense, intermediate format called bytecode.
This bytecode is executed by CPython’s internal Stack Machine.
The dis Module
The standard library provides the dis (disassembler) module to let us peer directly into this bytecode.
python · visualize
import disdef add(a, b): return a + b# Disassemble the function!dis.dis(add)
If you look closely at the output, you’ll see assembly-like instructions:
LOAD_FAST pushes the local variables a and b onto the evaluation stack.
BINARY_OP (or BINARY_ADD in older Python versions) pops two items off the stack, adds them, and pushes the result back.
RETURN_VALUE pops the top of the stack and returns it to the caller.
Code Objects
Every Python function has a __code__ attribute, which stores the compiled bytecode and metadata.
Understanding bytecode is the ultimate cheat code for performance optimization. Ever wondered why lst.append(1) is slightly faster than lst = lst + [1]?
Disassembling them reveals that the + operator has to use BUILD_LIST to create a temporary list in memory just to hold [1], whereas .append() mutates the existing list in place.
Check yourself
What is Python bytecode?
Reveal answer
An intermediate representation executed by the CPython virtual machine. — Python compiles source code to an intermediate representation (bytecode) which is then executed by the CPython interpreter (a stack-based virtual machine).
How does CPython's virtual machine process instructions?
Reveal answer
Using a stack-based architecture (pushing and popping values). — CPython uses an evaluation stack. Instructions like LOAD_FAST push values onto the stack, and BINARY_ADD pops them, adds them, and pushes the result back.
Why is `list.append(1)` generally faster than `list = list + [1]` in Python?
Reveal answer
`+` creates a new list and uses more bytecode instructions (like BUILD_LIST), whereas `append` mutates the list in place with fewer opcodes. — Disassembling both approaches shows that `+` has to build a temporary list and execute `BINARY_OP`, which involves more overhead than `LOAD_ATTR` and `CALL`.
Challenges
Challenge 1 +100 XP
Write a function `analyze(func)` that uses `dis.get_instructions(func)` to return a list of all unique opcode names (as strings) used in the function, sorted alphabetically.
python
Test 1 — expects "True\n"
Show solution (0 XP)
import disdef analyze(func): opnames = set(instr.opname for instr in dis.get_instructions(func)) return sorted(list(opnames))def sample(): a = 1 return aprint('RETURN_VALUE' in analyze(sample))
Challenge 2 +100 XP
Write a function `math_op()` that simply returns `60 * 60 * 24`. Then, print the length of its `__code__.co_consts` tuple.