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