Wow: list of immediate subclasses?

Tim Peters tim.one at comcast.net
Mon Aug 4 02:24:25 CEST 2003


[Roman Suzi]
> I wonder why to have __subclasses__() at all... I recall somebody
> (Tim Peters?) tolds us that classes are essentially just
> dictionaries - everything else is an imagination by OO-brains
> and fluffy operations like computing MRO. __subclasses__ aren't
> needed for OO to work. What for they really are? Just to have nice way
> to know subclasses? Why not to use some external framework for that
> task, hooking object manipulation to some routine if necessary?
>
> I can't find any reference to __subclasses__ in standard library!
> (I was looking for __subclasses__ string)

Looking for __subclasses__ won't answer it -- that's just Python exposing an
internal mechanism for the morbidly curious <wink>.

Look for uses of update_subclasses() instead, in typeobject.c.  At the C
level, Python doesn't want to do long-winded MRO searches for every
attribute reference for every type implemented in C, so "percolates down"
type object slot definitions from parent classes to their children at the
time child classes are first created.  Then the child class just has to look
at its own definitions.

This doesn't work, though, when a base class definition inherited by a child
class changes in the base class later, or when a new definition appears by
magic in the MRO (from the child's POV) before the base class originally
inherited from.  Since Python allows changing class characteristics at
runtime, this happens (albeit not in most peoples' code).  In such cases,
the freshly-mutated type object's tp_subclasses slot (that's the C spelling
of the Python-level __subclasses__) is used to figure out which derived
classes need to get their type object slots updated too.

In short, __subclasses__ exists to support efficient runtime class mutation
at the C level.  I view it much more as an accidental detail of the current
implementation than as a property of the language (Python would still be
Python if tp_subclasses/__subclasses__ didn't exist; CPython would simply be
slower (and possibly much slower) for some kinds of code then -- at heart,
it's to support an MRO-lookup caching/memoization gimmick).






More information about the Python-list mailing list