"‘self.values’ does not need to be an attribute of ‘self’... The most important programming knowledge is understanding how the entire system works across all its layers." In standard Python classes, unused attributes waste 8 bytes for a pointer plus dictionary entries, forcing multiple cache-line misses per point.
Tracing how a single Python statement p = Point3D(1.0, 2.0, 3.0); val = p.x executes across every hardware and runtime boundary:
LOAD_ATTR 1 (x)
STORE_FAST 2 (val)
In standard classes, LOAD_ATTR invokes _PyObject_GetAttr() looking through descriptors, then falling back to dictionary lookup.
PyDict_GetItemRef()
With __slots__, CPython replaces hash queries with immediate struct offset arithmetic: *(PyObject**)((char*)obj + slot_offset).
pools: 4KB / blocks: 16-512B
Small Python objects are served from internal pymalloc pools. Dynamic dict resizing triggers fragmented OS virtual allocations.
Packed: 2.6 pts/line
Slotted or packed representations fit neatly into CPU L1/L2 cache lines, enabling SIMD vectorization and avoiding pipeline stalls.
| Algorithm | Pass Mechanism | Time Complexity (Worst/Avg) | Space Overhead | System Cache Impact |
|---|---|---|---|---|
| Bubble / Selection Sort | Multiple quadratic sweeps (N passes) | O(N²) | O(1) | Severe thrashing; repeatedly swaps distant heap pointers. |
| Insertion Sort | Multiple localized sweeps (adaptive) | O(N²) / O(N) best | O(1) | High cache locality on tiny lists (<64 elements). |
| Timsort (Python .sort()) | Adaptive Runs Merge (O(log N) passes) | O(N log N) | O(N) | Exploits pre-existing ordered sequences; balanced pointer swaps. |
| Counting / Radix Sort | Single or fixed K-digit sweeps | O(N + K) | O(K) | Fast linear traversal, but restricted to integer/fixed-width keys. |
| Hash Index / Dictionary | Single-pass bucket indexing | O(N) load, O(1) probe | O(N) extra table | Fast amortized lookups at the cost of 2x-4x memory bloat. |
If arguments are checked late or errors handled loosely inside __init__, an invalid instantiation can create a half-initialized object missing .x, .y, or .z attributes, causing cryptic AttributeError downstream.
pt = NaivePoint3D("foo") # suppresses error
distance = pt.x + 10 # raises AttributeError: 'Point3D' object has no attribute 'x'
Enforce fail-fast construction. Either rely on native signature unpacking (which raises TypeError immediately before instantiation completes) or validate numbers eagerly.
pt = HardenedPoint3D("foo") # immediately raises TypeError at call site!
# Object never exists in invalid partial state.
Stashing self.values = [x, y, z] alongside attributes creates a redundant 56-byte list object + 24 bytes in float pointers + pointer in self.__dict__, doubling per-instance overhead for no benefit.
Using __slots__ = ('x', 'y', 'z') allocates exact 8-byte pointer offsets directly inside the C structure. Total footprint drops from ~152 bytes to ~56 bytes per coordinate.