scope of generators, class variables, resulting in global na
Jon Clements
joncle at googlemail.com
Wed Feb 24 10:45:05 EST 2010
On Feb 24, 12:21 pm, "Alf P. Steinbach" <al... at start.no> wrote:
> * Nomen Nescio:
>
> > Hello,
>
> > Can someone help me understand what is wrong with this example?
>
> > class T:
> > A = range(2)
> > B = range(4)
> > s = sum(i*j for i in A for j in B)
>
> > It produces the exception:
>
> > <type 'exceptions.NameError'>: global name 'j' is not defined
>
> Which Python implementation are you using?
>
> I can't reproduce the error message that you cite.
>
> <example>
> C:\test> py2
> Python 2.6.4 (r264:75708, Oct 26 2009, 08:23:19) [MSC v.1500 32 bit (Intel)] on
> win32
> Type "help", "copyright", "credits" or "license" for more information.
> >>> class T:
> ... A = range(2)
> ... B = range(4)
> ... s = sum(i*j for i in A for j in B)
> ...
> Traceback (most recent call last):
> File "<stdin>", line 1, in <module>
> File "<stdin>", line 4, in T
> File "<stdin>", line 4, in <genexpr>
> NameError: global name 'B' is not defined
> >>> exit()
>
> C:\test> py3
> Python 3.1.1 (r311:74483, Aug 17 2009, 17:02:12) [MSC v.1500 32 bit (Intel)] on
> win32
> Type "help", "copyright", "credits" or "license" for more information.
> >>> class T:
> ... A = range(2)
> ... B = range(4)
> ... s = sum(i*j for i in A for j in B)
> ...
> Traceback (most recent call last):
> File "<stdin>", line 1, in <module>
> File "<stdin>", line 4, in T
> File "<stdin>", line 4, in <genexpr>
> NameError: global name 'B' is not defined
> >>> exit()
>
> C:\test> _
> </example>
>
> Reason for the NameError:
>
> The above is a /generator expression/, evaluated in a class definition.
>
> The docs have a similar example but I'm sorry, I'm unable to find it! Anyway the
> generator expression is evaluated as if its code was put in function. And from
> within the scope of that function you can't access the class scope implicitly,
> hence, no access to 'B'.
>
> > The exception above is especially confusing since the following similar example
> > (I just replaced the generator by an explicit array) works:
>
> > class T:
> > A = range(2)
> > B = range(4)
> > s = sum([(i*j) for i in A for j in B])
>
> > (BTW, the class scope declarations are intentional).
>
> > Thanks, Leo.
>
> This is a /list comprehension/, not a generator expression (although
> syntactically it's almost the same).
>
> It obeys different rules.
>
> Essentially the generator expression produces a generator object that you may
> name or pass around as you wish, while the comprehension is just a syntactical
> device for writing more concisely some equivalent code that's generated inline.
>
> However, apparently the rules changed between Python 2.x and Python 3.x.
>
> In Python 3.x also the list comprehension fails in a class definition:
>
> <example>
> C:\test> py2
> Python 2.6.4 (r264:75708, Oct 26 2009, 08:23:19) [MSC v.1500 32 bit (Intel)] on
> win32
> Type "help", "copyright", "credits" or "license" for more information.
> >>> class T:
> ... A = range(2)
> ... B = range(4)
> ... s = sum([(i*j) for i in A for j in B])
> ...
> >>> exit()
>
> C:\test> py3
> Python 3.1.1 (r311:74483, Aug 17 2009, 17:02:12) [MSC v.1500 32 bit (Intel)] on
> win32
> Type "help", "copyright", "credits" or "license" for more information.
> >>> class T:
> ... A = range(2)
> ... B = range(4)
> ... s = sum([(i*j) for i in A for j in B])
> ...
> Traceback (most recent call last):
> File "<stdin>", line 1, in <module>
> File "<stdin>", line 4, in T
> File "<stdin>", line 4, in <listcomp>
> NameError: global name 'B' is not defined
> >>> exit()
>
> C:\test> _
> </example>
>
> From one point of view it's good that Py3 provides about the same behavior for
> generator expressions and list comprehensions.
>
> But I'd really like the above examples to Just Work. :-)
>
> Cheers & hth.,
>
> - Alf
s = sum( i*j for i,j in iterools.product(A, B) ) is a possible work
around.
Which could generalise to (something like):
s = sum( reduce(op.mul, seq) for seq in product(A, B, B, A) )
Cheers,
Jon.
More information about the Python-list
mailing list