Declaring a class level nested class?

Chris Rebert clp2 at rebertia.com
Thu Dec 3 00:13:03 EST 2009


On Wed, Dec 2, 2009 at 8:55 PM, cmckenzie <mckenzie.c at gmail.com> wrote:
> Hi.
>
> I'm new to Python, but I've managed to make some nice progress up to
> this point. After some code refactoring, I ran into a class design
> problem and I was wondering what the experts thought. It goes
> something like this:
>
> class module:
>   nestedClass
>
>   def __init__():
>      self.nestedClass = nested()
>      print self.nestedClass.nestedVar
>
>   class nested():
>      nestedVar = 1
>      def __init__(self):
>         print "Initialized..."
>
> I can't figure out what the correct way to construct the "nested"
> class so it can belong to "module".
>
> I want a class level construct of "nested" to belong to "module", but
> I keep getting nestedClass isn't defined.

Here's the scoping reason why it fails (remember that the nested class
is a class variable of the containing class):

<BEGIN PENDING FAQ SUBMISSION>

Why do I get errors when accessing class variables (a.k.a. static variables)?
-------------------------------------------------------------------------------------
If you try something like the following::

    class Foo(object):
        class_variable = 42

        def method(self, x):
            return x + class_variable


    Foo().method(7)

You'll get an error about Python being unable to find the class variable::

    Traceback (most recent call last):
     ...
    NameError: global name 'class_variable' is not defined

This is because class-level scope is not consulted when looking up
plain names in methods.  When looking up a name, the following scopes
are consulted, in order: Local variables, Variables in nested
functions, Global variables, and finally, Built-ins.

To refer to class variables, you must be more explicit. There are several
ways to go about it:

* Refer to the class by name::

    def method1(self, x):
        return x + Foo.class_variable

* Refer to the class of the object dynamically. If you class is
subclassed, this will allow the subclasses to override the value of
the class variable. ::

    def method2(self, x):
        return x + self.__class__.class_variable

* Exploit the fact that attribute lookups on an object fall back to
its class. Be warned that if you have both instance and class variables
with the same name, the instance variable will shadow
the class variable. ::

    def method3(self, x):
        return x + self.class_variable

* If your method is not truly an instance method
(i.e. does not utilize ``self``), make it a class method ::

    @classmethod
    def method4(cls, x):
        return x + cls.class_variable

<END FAQ EXCERPT>

However, there's pretty much no reason to nest classes anyway in
Python (it's not Java!). Just make them both top-level in the file. If
one class is only used internally in the module, just use the normal
private naming convention of starting its name with an underscore.

Also note that class names should generally use StudlyCaps, and that
naming a class "module" is rather confusing.

Cheers,
Chris
--
If the Python.org webmasters are listening, add the FAQ entry already!
http://blog.rebertia.com



More information about the Python-list mailing list