FAQ
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?

Thanks,


/larry/
//
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/python-list/attachments/20110413/8eb12e11/attachment-0001.html>

Search Discussions

  • James Mills at Apr 13, 2011 at 9:31 am

    On Wed, Apr 13, 2011 at 7:12 PM, Larry Hastings wrote:
    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?
    It's probably better to make use of modules here
    as opposed to nesting classes.

    cheers
    James

    --
    -- James Mills
    --
    -- "Problems are solved by method"
  • Jean-Michel Pichavant at Apr 13, 2011 at 10:08 am

    Larry Hastings 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?

    Thanks,


    /larry/
    class Outer:
    class Inner:
    class Worker:
    pass

    print 'Outer ', locals()
    class InnerSubclass(Inner):
    print 'InnerSubclass', locals()
    class Worker:
    pass

    Outer {'__module__': '__main__', 'Inner': <class __main__.Inner at
    0x963a7ac>}
    InnerSubclass {'__module__': '__main__'}

    I use myself nested classes a lot, but only as namespace / enum, meaning
    there is no inheritance involved. I don't think that you can do what you
    are trying to do.
    Outer would actually be a module, not a class.

    JM
  • Eric Snow at Apr 14, 2011 at 2:37 am

    On Wed, Apr 13, 2011 at 3:12 AM, Larry Hastings 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

    -------------- next part --------------
    An HTML attachment was scrubbed...
    URL: <http://mail.python.org/pipermail/python-list/attachments/20110413/07d99c84/attachment-0001.html>
  • Larry Hastings at Apr 14, 2011 at 3:40 am

    On 04/13/2011 07:37 PM, Eric Snow wrote:
    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: [...]
    It also means that Inner is not actually /in/ Outer, and the whole point
    was to have the class accessed as Outer.Inner. But I can get what I
    wanted, if immediately after the definition of Outer I have:

    Outer.Inner = Inner
    del Inner


    Thanks for the suggestion of "global Inner"! That makes this approach
    palatable.


    /larry/
    -------------- next part --------------
    An HTML attachment was scrubbed...
    URL: <http://mail.python.org/pipermail/python-list/attachments/20110413/21f4fb8a/attachment-0001.html>

Related Discussions

Discussion Navigation
viewthread | post
Discussion Overview
grouppython-list @
categoriespython
postedApr 13, '11 at 9:12a
activeApr 14, '11 at 3:40a
posts5
users4
websitepython.org

People

Translate

site design / logo © 2022 Grokbase