nesting class definitions?

Neel Krishnaswami neelk at brick.cswv.com
Thu Jan 27 19:13:57 EST 2000


Gerrit Holl <gerrit.holl at pobox.com> wrote:
> Hello,
> 
> I do see the point in nesting function definitions, namely as an alternative
> on places where one could use lambda. But what's the point in nesting
> class definitions? I know it's possible, but I've never seen it used.

I have used it, though for several reasons it's definitely not a
standard idiom.

(The pragmatic reason: according to Tim, Guido originally allowed
nested class and function definitions because it simplified the
grammar a little bit, and since in Python class and function
definitions are runtime statements rather than compile-time
declarations, there wasn't any additional cost on the interpreter
end. Now for a hopefully more enlightening explanation....)

>From time to time you will see nested function definitions; this is
largely because you can put things into the functions namespace, both
with regular arguments and through the default-argument hack for
faking closures. However, you hardly ever see nested class
definitions, because there really isn't a good way to communicate
information from the outer scope into the inner class's scope. (This
is a small lie, but bear with me.) That is, if you have the function

def class_factory(foo, bar, baz):
    quux = ... # some complicated computation...

    class Inner:
        ...
        # Note, there's no way to involve the contents of quux in
        # the definition of Inner! For example:
	#
	glark = frob(quux) # This won't work!
    ...
    return Inner

As a result, there's no real point to defining an inner class in
Python. If Python were lexically scoped, then quux would be visible
inside Inner's definition body, and there would be some small point to
nested classes. Even if it were possible, I doubt it would get used
much, though -- a class is a type, and most programmers prefer to set
up all their types as part of structuring their program. Generating
new classes at runtime is just hard to think about. Even in Common
Lisp, which has a well-defined facility for hacking the type system
called the metaobject protocol, programmers who make regular use of it
are considered wizardly and strange.

Now, you might notice that at the start of my post I mentioned that I
had used this, but I've spent my whole post explaining why no one
does. This is because of the small lie I mentioned before. Namely,
there *is* one way of communicating with the innards of Inner --
through the list of superclasses. In a class definition like

class Foo(Bar, Thud):
   ...

(Bar, Thud) is just an ordinary Python tuple -- there's nothing magic
about them, and as long as it is tuple of classes Python is perfectly
happy. Now, in languages with multiple inheritance, there is a style
of defining classes called "mixins" -- you create a set of classes,
each containing a separate capability, and then to create a class with
all of those capabilities you define a new class that inherits from
each mixin. (These classes are "mixed in", hence the name.)

So in one application I had, I had a number of mixins, and needed to
define a class based to handle some input data. If I had tried to
define a class for each possible combination, I would have had to
define a *bunch* of classes (I think something like 60), and as a
result I defined a function like this:

def class_factory(*mixins):
    class Anonymous:
        # some various routines
    Anonymous.__bases__ = tuple(mixins)
    return Anonymous

so that I could call class_factory() to create the appropriate class
at runtime.
 

Neel



More information about the Python-list mailing list