Back to articles

Disassembling Python Bytecode: How the Virtual Machine Executes Code

August 8, 20265 min read
Python
Compiler
Bytecode
Internals

CPython compiles Python source code into bytecode before executing it on a stack-based virtual machine. Analyzing bytecode gives engineers deep insight into language mechanics and runtime performance.

The dis Module

Python’s built-in dis module lets us inspect the exact bytecode instructions generated by the compiler.

import dis

def compute_sum(numbers: list[int]) -> int:
    total = 0
    for num in numbers:
        total += num
    return total

print("--- Bytecode for compute_sum ---")
dis.dis(compute_sum)

Comparing List Comprehensions vs. Map/Filter

Let’s inspect why list comprehensions in Python are generally faster than for loops appending to a list:

import dis

def method_append(data: list[int]):
    result = []
    for item in data:
        if item % 2 == 0:
            result.append(item * 2)
    return result

def method_comprehension(data: list[int]):
    return [item * 2 for item in data if item % 2 == 0]

print("--- Append Method ---")
dis.dis(method_append)

print("\n--- Comprehension Method ---")
dis.dis(method_comprehension)

Key Observations

  • List comprehensions utilize optimized LIST_APPEND opcodes directly on the evaluation stack without performing global scope lookups for .append.
  • Modern CPython (3.11+) features Adaptive Bytecode Execution (PEP 659), which dynamically specializes opcodes at runtime based on type feedback.