[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.python

Instance of inherited nested class in outer class not allowed?

mrstephengross

2/27/2008 3:56:00 PM

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
4 Answers

Diez B. Roggisch

2/27/2008 6:29:00 PM

0

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

mrstephengross

2/27/2008 6:53:00 PM

0

> 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

Gabriel Genellina

2/27/2008 7:58:00 PM

0

En Wed, 27 Feb 2008 16:52:57 -0200, mrstephengross
<mrstevegross@gmail.com> 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

Diez B. Roggisch

2/27/2008 10:16:00 PM

0

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