Why nested scope rules do not apply to inner Class?

Maric Michaud maric at aristote.info
Tue Aug 12 07:11:06 EDT 2008


Le Tuesday 12 August 2008 11:29:18 Cousson, Benoit, vous avez écrit :
> Hi,
>
> I'd like to be able to use a nested class (C1) from another sibling nested
> class (C3). This looks very similar to the nested scopes of functions
> except that it does not work.
>
> class A(object):
> 	pass
>
> class B(object):
>
> 	class C1(object):
> 		pass
>
> 	class C2(C1):
> 		foo = A
>
> 	class C3(object):
> 		foo = C1
>
> The funny thing is that C2 can inherit from C1 but C3 cannot reference C1.
> B.C1 does not work either, but in that case it makes sense since B is still
> being defined. Is this a language limitation or something that does not
> make sense at all?
>

This is a language limitation.
This is because nested scope is implemented for python function only since 2.3 
allow late binding of free variables. the scope in class statment is not a 
closure, so there is only two possible scope in it : local and global.

When "class C2(C1):" statment is interpreted, it is in the scope of class B 
for which a name C1 exists, but it doesn't within the new scope of class C2 
(the future C2.__dict__).

If you really need such a nested thing, this could help :

>>>[39]: class A(object) :
    class B(object) : pass
    C = type('C', (B,), {'ref' : B})
   ....:

>>>[29]:

>>>[30]: A
...[30]: <class '__main__.A'>

>>>[31]: A.B
...[31]: <class '__main__.B'>

>>>[32]: A.C
...[32]: <class '__main__.C'>

>>>[33]: A.C.__bases__
...[33]: (<class '__main__.B'>,)

>>>[34]: A.C.ref
...[34]: <class '__main__.B'>





> I'm wondering as well if the new nonlocal statement will fix that in py3k?
>

nonlocal doesn't adress this issue an I doubt python 3.0 fix it at all.

You have the same problem with generator expressions, which bind lately outer 
loop variables :

>>>[70]: def f() :
    l = list( a for a in range(5) )
    return list( e + f for f in range(5) for e in l )
   ....:

>>>[73]: list(f())
...[73]: [0, 1, 2, 3, 4, 1, 2, 3, 4, 5, 2, 3, 4, 5, 6, 3, 4, 5, 6, 7, 4, 5, 6, 
7, 8]

>>>[74]: class A(object) :
    l = list( a for a in range(5) )
    m = [ e + f for f in range(5) for e in l ]
   ....:
   ....:

>>>[77]: A.m
...[77]: [0, 1, 2, 3, 4, 1, 2, 3, 4, 5, 2, 3, 4, 5, 6, 3, 4, 5, 6, 7, 4, 5, 6, 
7, 8]

>>>[78]: class A(object) :
    l = list( a for a in range(5) )
    m = list( e + f for f in range(5) for e in l )
   ....:
   ....:
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)

/home/maric/<ipython console> in <module>()

/home/maric/<ipython console> in A()

/home/maric/<ipython console> in <genexpr>((f,))

NameError: global name 'l' is not defined


-- 
_____________

Maric Michaud



More information about the Python-list mailing list