On Feb 24, 12:21 pm, "Alf P. Steinbach" <al...@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. -- http://mail.python.org/mailman/listinfo/python-list