Nested inner classes and inheritance -> namespace problem

Eric Snow ericsnowcurrently at gmail.com
Wed Apr 13 22:37:28 EDT 2011


On Wed, Apr 13, 2011 at 3:12 AM, Larry Hastings <larry at hastings.org> wrote:

>
> The problem: if you're currently in a nested class, you can't look up
> variables in the outer "class scope".
>
> For example, this code fails in Python 3:
>
> class Outer:
>   class Inner:
>     class Worker:
>       pass
>
>   class InnerSubclass(Inner):
>     class Worker(Inner.Worker):
>       pass
>
> It fails at the definition of Worker inside InnerSubclass.  Python 3 can't
> find "Inner", in order to get to "Inner.Worker".
>
> Adding "global Inner" just above that line doesn't help--it's not a global.
> Adding "nonlocal Inner" just above that line doesn't help either--I suppose
> it's the *wrong kind* of nonlocal.  nonlocal is for nested functions, and
> this uses nested classes.
>
> You can tell me YAGNI, but I tripped over this because I wanted it.  It's
> not a contrived example.  I actually use inner classes a lot; I suppose I'm
> relatively alone in doing so.
>
> Yes, I could make the problem go away if I didn't have nested inner classes
> like this.  But I like this structure.  Any idea how I can     make it work
> while preserving the nesting and inheritance?
>


Hi Larry,

My understanding is that the problem revolves around how classes are built.
 The body of the inner class has access to itself and to the globals, and to
whatever locals may be around (if defined inside a function).  So if you
want to see something, you have to put it in one of those.  I suppose you
could try something like this:

class Outer:
  global Inner
  class Inner:
    class Worker:
      pass

  class InnerSubclass(Inner):
    class Worker(Inner.Worker):
      pass

However, that pollutes your global namespace.  If you are worried about that
you could try:

def namespaces():
    Inner  = None
    class Outer:
      nonlocal Inner
      class Inner:
        class Worker:
          pass
      class InnerSubclass(Inner):
        class Worker(Inner.Worker):
          pass
    return Outer

However, this freaks out because Inner does not get bound to Outer, even
though it is available to Worker.  You can use function locals but you lose
your clean nesting:

def namespaces():
    class Something:
      pass
    class Outer:
      class Inner:
        class Worker:
          pass
      class InnerSubclass(Inner):
        class Worker(Something):
          pass
    return Outer

 Anyway, definitely a weird problem.  Maybe the class body should be able to
access the namespaces that wrap it, like functions do...  Not that I have
found them, but I would not be surprised if there have been plenty of
discussions around class body namespaces and nesting and closure...  It
would be great if it just worked, or at the very least you could do
something like this:

class Outer:
  class Inner:
    class Worker:
      pass
  class InnerSubclass(Inner):
    nonlocal Inner
    class Worker(Inner.Worker):
      pass
return Outer

That would pull Inner into the namespace of InnerSubclass, allowing Worker
to use it in the bases declaration.

If you really want to get crazy, I suppose you could do so metaclass
hackery...

-eric


> Thanks,
>
>
> *larry*
> **
>
> --
> http://mail.python.org/mailman/listinfo/python-list
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/python-list/attachments/20110413/07d99c84/attachment-0001.html>


More information about the Python-list mailing list