Nomen Nescio wrote: > 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
It's due to scoping rules for classes and/or how generator expressions are compiled. When a function definition is executed from within the body of a class, the body of the class doesn't act as an outer scope for it. E.g. class A: x = 2 def f(self): return x When f is defined (technically, when the closure is made), the name 'x' is not bound to 2 but is considered to be in the global namespace (unless the class is defined within a function for example). Now generator expressions are defined as generator functions so your example is akin to something like: class T: A = range(2) B = range(4) def _gen(L): for i in L: for j in B: yield i*j s = sum(_gen(A)) (From memory, I might be wrong on some details) Now looking at the above, when _gen is defined, B is considered to be belonging to the global namespace, therefore if it is not defined there a NameError will be thrown. Now a safe workaround to this would be: class T: A = range(2) B = range(4) s = (lambda A=A, B=B: sum(i*j for i in A for j in B))() The lambda form is evaluated when the body of the class is executed, binding the names A and B to the objects you want in the generator expression. I remember suggesting a while ago that all generator expressions be implicitely wrapped like the one above in order to avoid such surprises. I can't quite remember what the arguments against were, but you can probably find them in the archives! -- Arnaud -- http://mail.python.org/mailman/listinfo/python-list