On Jan 17, 3:55 pm, Peter Otten <[EMAIL PROTECTED]> wrote: > Here is a simpler example: > > >>> class A: > > ... a = 42 > ... list(a for _ in "a") > ... > Traceback (most recent call last): > File "<stdin>", line 1, in <module> > File "<stdin>", line 3, in A > File "<stdin>", line 3, in <genexpr> > NameError: global name 'a' is not defined [...] > So it seems that Python gets puzzled by the extra scope introduced by the > genexp, i. e. you are seeing an obscure variant of the following > (expected) behaviour: > > >>> class B: > > ... a = 42 > ... def f(): a > ... f() > ... > Traceback (most recent call last): > File "<stdin>", line 1, in <module> > File "<stdin>", line 4, in B > File "<stdin>", line 3, in f > NameError: global name 'a' is not defined
This is exactly the problem: class A: a = 42 list(a for _ in "a") is in fact compiled as: class A: a = 42 def _genexpr(): for _ in "a": yield a list(_genexpr()) Except that the _genexpr function is not bound to any name, just left on the stack for list to pick up next. This can be checked using the dis module. Trying it yields exactly the same error: >>> class A(object): ... a = 42 ... def _genexpr(): ... for _ in "a": ... yield a ... list(_genexpr()) ... Traceback (most recent call last): File "<stdin>", line 1, in <module> File "<stdin>", line 6, in A File "<stdin>", line 5, in _genexpr NameError: global name 'a' is not defined > I think you should file a bug report, though making the genexp recognizing > the class scope probably isn't worth the effort. It isn't necessary to do that to fix the problem. I think that the semantics of genexprs concerning free variables are confusing (and this is a good example!). I suggested a change on python-ideas a while ago that would solve this particular issue. In short, all free variables inside a generator expression could be bound at the creation of the expression, not when it is evaluated. So for example ((c, f(x)) for x in L) would be the equivalent of what one could currently write as. (lambda _c, _f: ((c, f(x) for x in L))(c, f) so your example would compile to: class A: a = 42 def _genexpr(_a): for _ in "a": yield _a list(_genexpr(a)) Which would behave as the OP expected (and I think as it is reasonable to expect if one doesn't know about how genexprs are implemented). Other reasons why I think this is desirable are exposed (maybe not very convincingly) in this post to python-ideas. http://mail.python.org/pipermail/python-ideas/2007-December/001260.html -- Arnaud -- http://mail.python.org/mailman/listinfo/python-list