Instance of inherited nested class in outer class not allowed?

Discussion in 'Python' started by mrstephengross, Feb 27, 2008.

  1. I've got an interesting problem with my class hierarchy. I have an
    outer class, in which two nested classes are defined:

    class Outer:
    class Parent:
    def __init__ (self):
    print "parent!"
    class Child(Parent):
    def __init__ (self):
    Outer.Parent.__init__(self)
    foo = Child()

    Note that the second nested class (Outer.Child) inherits from the
    first nested class (Outer.Parent). When I run the above code, python
    reports a name error:

    Traceback (most recent call last):
    File "./temp.py", line 3, in ?
    class Outer:
    File "./temp.py", line 13, in Outer
    foo = Child()
    File "./temp.py", line 11, in __init__
    Outer.Parent.__init__(self)
    NameError: global name 'Outer' is not defined

    Apparently, python doesn't like having an instance of a derived nested
    class present in the outer class. Interestingly enough, if I change
    the foo variable to an instance of the parent class:

    foo = Parent()

    everything is hunky-dory. Is there some syntax rule I'm breaking here?

    Thanks!
    --Steve
    mrstephengross, Feb 27, 2008
    #1
    1. Advertising

  2. mrstephengross schrieb:
    > I've got an interesting problem with my class hierarchy. I have an
    > outer class, in which two nested classes are defined:
    >
    > class Outer:
    > class Parent:
    > def __init__ (self):
    > print "parent!"
    > class Child(Parent):
    > def __init__ (self):
    > Outer.Parent.__init__(self)
    > foo = Child()
    >
    > Note that the second nested class (Outer.Child) inherits from the
    > first nested class (Outer.Parent). When I run the above code, python
    > reports a name error:
    >
    > Traceback (most recent call last):
    > File "./temp.py", line 3, in ?
    > class Outer:
    > File "./temp.py", line 13, in Outer
    > foo = Child()
    > File "./temp.py", line 11, in __init__
    > Outer.Parent.__init__(self)
    > NameError: global name 'Outer' is not defined
    >
    > Apparently, python doesn't like having an instance of a derived nested
    > class present in the outer class. Interestingly enough, if I change
    > the foo variable to an instance of the parent class:
    >
    > foo = Parent()
    >
    > everything is hunky-dory. Is there some syntax rule I'm breaking here?


    It's simple - you try to refer to Outer whilst Outer itself is being
    created. A much simpler version of your problem is this:


    class Foo:
    foo = Foo()

    You have to live with that. Just do

    Outer.foo = Outer.Parent()

    after your class-statement to achieve the same result.

    Diez
    Diez B. Roggisch, Feb 27, 2008
    #2
    1. Advertising

  3. > class Foo:
    > foo = Foo()
    >
    > You have to live with that. Just do
    > Outer.foo = Outer.Parent()
    > after your class-statement to achieve the same result.


    Hmmm. Well, I see why that works. It's too bad, though. If I want to
    keep all executed code safely within a "if __name__ == '__main__'"
    block, it ends up a bit ugly. Then again, I guess this is just an
    aspect of python I'll have to get used to. Is there a specific reason
    it works this way, by chance?

    --Steve
    mrstephengross, Feb 27, 2008
    #3
  4. En Wed, 27 Feb 2008 16:52:57 -0200, mrstephengross
    <> escribi�:

    >> class Foo:
    >> foo = Foo()
    >>
    >> You have to live with that. Just do
    >> Outer.foo = Outer.Parent()
    >> after your class-statement to achieve the same result.

    >
    > Hmmm. Well, I see why that works. It's too bad, though. If I want to
    > keep all executed code safely within a "if __name__ == '__main__'"
    > block, it ends up a bit ugly. Then again, I guess this is just an
    > aspect of python I'll have to get used to. Is there a specific reason
    > it works this way, by chance?


    class statements (and def, and almost everything in Python) are
    *executable* statements, not declarations.
    When you import a module, it is executed. If it contains a class
    statement, it is executed as follows: create an empty namespace (a dict),
    execute the class body in it, create a new class object with __dict__ =
    that namespace, and finally, bind the class name to the newly created
    class object in the module namespace.
    Until that last step, you can't refer to the class being created by name.

    I don't get your issue with "if __name__==__main__", but I hope that you
    now understand a bit better why a late initialization is required. (Of
    course someone could come up with a metaclass to perform that late
    initialization, but the important thing is to understand that you cannot
    create an instance before the class itself exists)

    --
    Gabriel Genellina
    Gabriel Genellina, Feb 27, 2008
    #4
  5. mrstephengross schrieb:
    >> class Foo:
    >> foo = Foo()
    >>
    >> You have to live with that. Just do
    >> Outer.foo = Outer.Parent()
    >> after your class-statement to achieve the same result.

    >
    > Hmmm. Well, I see why that works. It's too bad, though. If I want to
    > keep all executed code safely within a "if __name__ == '__main__'"
    > block, it ends up a bit ugly. Then again, I guess this is just an
    > aspect of python I'll have to get used to. Is there a specific reason
    > it works this way, by chance?


    Well, what would you think python should make of this?

    class Foo:

    f = Foo()

    def __init__(self, argument):
    pass


    It can't possibly allow to instantiate an object of a class unless the
    class creation is finished. Of course it could delay the execution of
    anything but method definitions. But then the price would be high - loss
    of generatlity, and for example this weren't possible as well:

    class Bar:
    if relative_moon_moisture() > 10:
    def foo(self): pass
    else:
    def bar(self): pass


    Diez
    Diez B. Roggisch, Feb 27, 2008
    #5
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Heiko Henkelmann
    Replies:
    2
    Views:
    484
    Heiko Henkelmann
    Apr 27, 2004
  2. Richard Lee
    Replies:
    4
    Views:
    1,024
    James Kanze
    Mar 6, 2008
  3. DBak
    Replies:
    11
    Views:
    993
  4. 7stud --
    Replies:
    11
    Views:
    389
    7stud --
    Nov 9, 2007
  5. Iñaki Baz Castillo
    Replies:
    13
    Views:
    483
    Iñaki Baz Castillo
    May 1, 2011
Loading...

Share This Page