generator expression works in shell, NameError in script

M

Miles Kaufmann

... bar = ['a', 'b', 'c']
... baaz = list((b, b) for b in bar)

but it indeed looks like using bar.index *in a generator expression*
fails (at least in 2.5.2) :
... bar = ['a', 'b', 'c']
... baaz = list((bar.index(b), b) for b in bar)
...
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 3, in Foo
File "<stdin>", line 3, in <genexpr>
NameError: global name 'bar' is not defined

The reason that the first one works but the second fails is clearer if
you translate each generator expression to the approximately
equivalent generator function:

class Foo(object):
bar = ['a', 'b', 'c']
def _gen(_0):
for b in _0:
yield (b, b)
baaz = list(_gen(iter(bar))

# PEP 227: "the name bindings that occur in the class block
# are not visible to enclosed functions"
class Foo(object):
bar = ['a', 'b', 'c']
def _gen(_0):
for b in _0:
yield (bar.index(b), b)
baaz = list(_gen(iter(bar))

-Miles
 
G

greg

guthrie said:
-- I don't get this - the only local loop variable is "e", not lst.

Yes, but the whole list comprehension gets put into
a nested function, including the part that evaluates
lst. (It's not strictly *necessary* to do that, but
that's the way it happens to be implemented at the
moment.)
It would generally be the case that a nested function would have
access to its enclosing scope.

Usually, but class namespaces are a special case --
they're not considered to be enclosing scopes, even
though textually they're written that way.
it certainly appears un-intuitive

It is, but it's hard to see what could be done to
improve the situation without introducing worse
problems.
 
S

ssc

Why are you doing this? I'm assuming a code to title look up is
required (don't forget military, royal and honorable titles
etc... :) )

I'm in New Zealand. Hardly any need for military titles, rarely any
for royal and damn sure none for honorable :-D (scnr)
 
A

alito

On Jun 17, 6:38 pm, Steven Samuel Cole <[email protected]>
wrote:
Your code certainly looks reasonable, and looks to me like it "should"
work. The comment of partial namespace is interesting, but
unconvincing (to me) - but I am not a Python expert! It would
certainly seem that within that code block it is in the local
namespace, not removed from that scope to be in another.
Seems that it should either be a bug, or else is a design error in the
language!
Just as in the above noted "WTF" - non-intuitive language constructs
that surprise users are poor design.

This is certainly an odd one. This code works fine under 2.6 but fails
in Python 3.1.

...     lst=[2]
...     gen=[lst.index(e) for e in lst]
...
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 3, in x
  File "<stdin>", line 3, in <listcomp>
NameError: global name 'lst' is not defined

Arghh. I see thousands of future wtf!? posts to c.l.p. triggered by
this new feature. Might as well save some time and add it to the FAQ
already.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,780
Messages
2,569,608
Members
45,252
Latest member
MeredithPl

Latest Threads

Top