12

I'm running on Python 2.7.8 (Anaconda Distribution) and this code fails. This looks like a bug in the Python implementation, but am I missing anything?

class C:
    x = {2 : 1}
    y = {w for w in x if x[w]==1}

Running this code gives the following error message:

NameError: global name 'x' is not defined

The error message also seems wrong to me.

Note that the following two very similar pieces of code do work with no problems:

# this works fine:
class C:
    x = {2 : 1}
    y = [w for w in x if x[w]==1]


# this works fine too:
x = {2 : 1}
y = {w for w in x if x[w]==1}
greg
  • 221
  • 1
  • 6
  • 1
    how are you running it? There is no error in what you have provided – Padraic Cunningham Jan 14 '15 at 17:08
  • It fails on the interactive interpreter and also in an ipython notebook – greg Jan 14 '15 at 17:09
  • Are you trying to create a new set based on a specific filtering criterion? – Makoto Jan 14 '15 at 17:10
  • 1
    it works fine for me. After defining the class, I run `foo = C(); print foo.x; print foo.y` – MattDMo Jan 14 '15 at 17:11
  • Works for me, too, when creating the class, and I can execute the same code @MattDMo did with success. That's with `python` 2.7.3. However, I also tried `ipython` 0.12 and it failed as stated. – lurker Jan 14 '15 at 17:12
  • 1
    ok I can replicate in ipython when creating the class using python 2.7.6 and 3.4.2 – Padraic Cunningham Jan 14 '15 at 17:12
  • ok, I think it's settled: the link @PascalBugnion gives claims it's a bug by design, which happens because of weird scoping rules related to set comprehensions. Apparently it's because set comprehensions were backported to Python 2.7, and the way to solve it is just to upgrade to version 3.0, or try to not use set comprehensions when they vreak like this. – greg Jan 14 '15 at 17:17
  • Thanks for the help. Sorry for wasting everyone's time! – greg Jan 14 '15 at 17:19
  • @mobiusdumpling: see the dupe I used to close your question, there are other ways. – Martijn Pieters Jan 14 '15 at 17:19
  • set([w for w in x if x[w]==1]) will work. but you already know that :) replicated in Ipython (2.7) – srj Jan 14 '15 at 17:19
  • Update to my other comment - the original code worked for me with 2.7.9 in Windows, but when I ran it with 2.7.8 in Linux, I got the same error. Interesting... – MattDMo Jan 14 '15 at 17:21
  • @MartijnPieters, the dupe answer suggests this is a bug fixed in python 3 but I can replicate using python 3.4.2 in ipython – Padraic Cunningham Jan 14 '15 at 17:28
  • 1
    @PadraicCunningham: the fact that list comprehensions *don't* have a scope was the bug. Using a list comprehension will produce the same behaviour as set and dictionary comprehensions (and generator expressions) in Python 3. The behaviour is *by design*. – Martijn Pieters Jan 14 '15 at 17:30
  • @PadraicCunningham: please do read the whole answer carefully. – Martijn Pieters Jan 14 '15 at 17:30
  • @MartijnPieters, but why does the code work using pycharm and work for some people on windows and not on linux? – Padraic Cunningham Jan 14 '15 at 17:32
  • 1
    @PadraicCunningham: Testing errors. Usually because they have a preexisting global. – Martijn Pieters Jan 14 '15 at 17:33
  • 3
    @MattDMo: Now start a fresh session where you do **not** have a preexisting global `x`. The set comprehension looks for a global, not the name in the class scope (which is not a scope as far as nesting is concerned). If it worked anyway, you had a global named `x` already. – Martijn Pieters Jan 14 '15 at 17:34
  • @MartijnPieters, yep. – Padraic Cunningham Jan 14 '15 at 17:35
  • @Martijn you're right. I had tested the `x = {2 : 1}; y = {w for w in x if x[w]==1}` code in my session before defining the class. I restarted my session, and got the error. – MattDMo Jan 14 '15 at 19:18

0 Answers0