* 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
--
http://mail.python.org/mailman/listinfo/python-list