Skip to content

O02, following the type pointer - #132

Merged
tamnd merged 1 commit into
mainfrom
o02-following-the-type-pointer
Aug 31, 2026
Merged

O02, following the type pointer#132
tamnd merged 1 commit into
mainfrom
o02-following-the-type-pointer

Conversation

@tamnd

@tamnd tamnd commented Aug 31, 2026

Copy link
Copy Markdown
Owner

O01 read the sixteen bytes at the front of an object and stopped at the second word, which is a pointer to the type. This lesson follows it.

What is on the other end is the largest struct in the interpreter, and almost all of it is answers to questions about instances rather than about the type. Most of those answers are readable from Python with no C at all.

What the lesson covers:

  • following the type pointer from any object reaches type in at most two steps, and type points at itself, because the chain has to end somewhere and a loop is cheaper than a special case every lookup would have to check for
  • tp_basicsize and tp_itemsize are the two numbers that say how big one instance is, and multiplying them out matches __sizeof__ for tuples and bytes and misses badly for list, whose items are a separate allocation
  • type.__basicsize__ is nine hundred odd bytes because PyType_Type sets its own basicsize to sizeof(PyHeapTypeObject), so an instance of type is a class and a class carries all the operator tables inline
  • the flags word tells a static type from a heap type, and Py_TPFLAGS_IMMUTABLETYPE is the entire reason int.nope = 1 raises and Plain.nope = 1 does not
  • tp_dictoffset has four meanings: zero, a positive offset, a negative offset counted from the end of a var sized object, and exactly -1, which is a sentinel and not an offset, asserted against in the code that resolves the ordinary ones
  • what -1 means is that the pointer lives in front of the object, three pointers back, with the weakref list one further back and the two words of GC pre header in between, which is why sys.getsizeof reports thirty two bytes more than an instance claims for itself
  • and a class statement is a function call: the body compiles to a function, __build_class__ runs it, and the metaclass turns the namespace into a type, so type("Greeter", (), {"hi": hi}) comes out with the same flags, basicsize and mro

Everything is cited against v3.15.0rc1: _typeobject, PyHeapTypeObject, PyType_Type, Py_TPFLAGS_HEAPTYPE, tp_dictoffset, tp_weaklistoffset, _PyObject_ComputedDictPointer, MANAGED_DICT_OFFSET, _PyType_PreHeaderSize, _PyType_AllocNoTrack and builtin___build_class__.

Six diagrams. The notebook runs in Colab and all nine of its cells run in the browser probe, which is now at 30 lessons and 319 cells.

Two cells differ between 3.14 and 3.15 and both say so: type.__basicsize__ moved from 936 to 944, and the implicit return at the end of a module went from LOAD_CONST to LOAD_COMMON_CONSTANT. Two more carry a note about the browser, where a pointer is four bytes and __weakrefoffset__ reads minus sixteen.

Three glossary terms went in: static type, heap type and metaclass. type object picked up a citation and two cross references while I was there. GLOSSARY.md is at 111.

Part of #23.

The second lesson of the object model part. O01 stopped at the second word
of the header, which is a pointer to the type. This one follows it.

The lesson reads the type struct from Python: basicsize and itemsize and
what they do and do not predict, the flags word and the one bit behind
cannot set attribute of immutable type, and the two offset fields where a
negative number means one thing except when it is minus one, which is a
sentinel meaning the interpreter manages the dict itself and the pointer
lives three words in front of the object.

It closes with the class statement, which compiles to a call to
__build_class__ and nothing else.

Three glossary terms: static type, heap type and metaclass. Six diagrams.
Two cells differ between 3.14 and 3.15 and both carry a note.
@tamnd tamnd added kind/lesson A chapter: prose, notebook, experiments, boss fight area/objects The object model, types, slots and the builtin types labels Aug 31, 2026
@tamnd
tamnd merged commit 3929038 into main Aug 31, 2026
16 checks passed
@tamnd
tamnd deleted the o02-following-the-type-pointer branch August 31, 2026 15:54
@tamnd tamnd mentioned this pull request Aug 31, 2026
6 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/objects The object model, types, slots and the builtin types kind/lesson A chapter: prose, notebook, experiments, boss fight

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant