Skip to content

O03, dunders and the slots behind them - #133

Merged
tamnd merged 1 commit into
mainfrom
o03-dunders-and-slots
Aug 31, 2026
Merged

O03, dunders and the slots behind them#133
tamnd merged 1 commit into
mainfrom
o03-dunders-and-slots

Conversation

@tamnd

@tamnd tamnd commented Aug 31, 2026

Copy link
Copy Markdown
Owner

O02 opened the type struct and walked straight past the interesting part. In the middle of it are about seventy fields that are function pointers, and the interpreter reads them directly: repr(x) is a load out of Py_TYPE(x)->tp_repr and an indirect call.

But nobody writes tp_repr. You write __repr__. The thing in between is a table of ninety four rows in typeobject.c, and this lesson is about that table being walked in both directions.

What the lesson covers:

  • backwards, add_operators turns every filled slot on a C type into a slot wrapper in the class dict, which is where int.__add__ and object.__repr__ come from, and type(int.__add__).__name__ is how you tell one from an ordinary method
  • forwards, fixup_slot_dispatchers puts a generic dispatcher into every slot whose dunder you defined, and that dispatcher looks the name up on the type each time it runs
  • which is the whole reason a __repr__ set on an instance is ignored: it really is in the instance dict, you can call it by name, and repr() goes through the slot and never looks there
  • and the reason assigning one to a class works an hour later, on that class and every subclass, because type.__setattr__ calls update_slot
  • __len__ fills mp_length and sq_length, which is why a class with only a length gets truthiness
  • __getitem__ fills mp_subscript and sq_item, and sq_item is the old sequence protocol, so a class with one __getitem__ and nothing else is iterable and supports in
  • __add__ and __radd__ share nb_add, so the dispatcher has the decision written into it: the reflected call goes first only if the right hand type is a subclass and defines the method itself rather than inheriting it
  • and defining __eq__ without __hash__ is not a rule, it is overrides_hash stopping the slot being inherited and then type_ready_set_hash writing a literal None into the class dict, which you can look at

Everything is cited against v3.15.0rc1: slotdefs and the comment above it, TPSLOT, SLOT0, SLOT1BINFULL, add_operators, fixup_slot_dispatchers, update_slot, overrides_hash and type_ready_set_hash.

Six diagrams. Every cell prints exactly the same thing on 3.14, on 3.15 and in the browser probe, so nothing in this one needed a version note. The probe is at 31 lessons and 328 cells.

Two glossary terms went in: slot and slot wrapper. GLOSSARY.md is at 113.

Part of #23.

O02 walked past the seventy odd function pointer fields in the middle of
the type struct. This lesson is about those and about the table of ninety
four rows that connects them to the names you actually write.

The table gets walked both ways. Backwards by add_operators when a C type
is made ready, which is where int.__add__ comes from. Forwards by
fixup_slot_dispatchers when you write a class, which puts a generic
dispatcher in the slot that looks your function up on the type every time
it runs.

Four things people learn as separate rules come out of that: a dunder set
on an instance is ignored, one assigned to a class takes effect at once and
on every subclass, __getitem__ alone makes a class iterable because it
fills sq_item, and __eq__ without __hash__ leaves a literal None in the
class dict, put there by two mechanisms meeting.

Two glossary terms: slot and slot wrapper. Six diagrams. Every cell prints
the same thing on 3.14, on 3.15 and in the browser.
@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 6c3d02a into main Aug 31, 2026
16 checks passed
@tamnd
tamnd deleted the o03-dunders-and-slots branch August 31, 2026 16:12
@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