Wandering Thoughts archives

2020-12-24

In CPython, types implemented in C actually are part of the type tree

In Python, in theory all types descend from object (they are direct or indirect subclasses of it). For years, I've believed (and written) that this was not the case at the implementation level for types written in native C code in CPython (the standard implementation of Python and the one you're probably using). Types written in C might behave as if they descended from object, but I thought their behavior was actually entirely stand-alone, implemented by each type separately in C. Courtesy of Python behind the scenes #6: how Python object system works, I've discovered that I'm wrong.

In CPython, C level Python types are not literally subclasses of the C level version of object, because of course C doesn't have classes and subclasses in that sense. Instead, you usually describe your type by defining a PyTypeObject struct for it, with all sorts of fields that you fill in or don't fill in as you need them, including a tp_base field for your base type (if you want more than one base type, you need to take the alternate path of a heap type). When CPython needs to execute special methods or other operations on your type, it will directly use fields on your PyTypeObject structure (and as far as I know, it only uses those fields, with no fallbacks). On the surface, this looks like the tp_base field is essentially decorative and is only used to report your claimed __base__ if people ask.

However, there is a bit of CPython magic hiding behind the scenes. In order to actually use a PyTypeObject as a type, you must register it and make it ready by calling PyType_Ready. As part of this, PyType_Ready will use your type's tp_base to fill in various fields of your PyTypeObject if you didn't already do that, which effectively means that your C level type will inherit those fields from its base type (and so on all the way up to object). This is outlined in a section of the C API, but of course I never read the C API myself because I never needed to use it. The how [the] Python object system works article has more details on how this works, if you're curious, along with details on how special methods also work (which is more interesting than I had any idea, and I've looked at this area before).

(The distinction between what is considered a 'type' and what is considered a 'class' by repr() is somewhat arbitrary; see the sidebar here. C level things defined with PyTypeObject will probably always be considered types instead of classes.)

python/CPythonCTypesHaveTree written at 00:05:53; Add Comment


Page tools: See As Normal.
Search:
Login: Password:
Atom Syndication: Recent Pages, Recent Comments.

This dinky wiki is brought to you by the Insane Hackers Guild, Python sub-branch.