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.)
Comments on this page:
|
|