pyflakes icon indicating copy to clipboard operation
pyflakes copied to clipboard

Undefined comprehension variable in class body not caught

Open asmeurer opened this issue 4 years ago • 3 comments

class Test:
    a = [1, 2, 3]
    b = [1, 2, 3]
    c = [i*j for i in a for j in b]

Pyflakes gives no errors here. But believe it or not, this raises a NameError

Traceback (most recent call last):
  File "test.py", line 1, in <module>
    class Test:
  File "test.py", line 4, in Test
    c = [i*j for i in a for j in b]
  File "test.py", line 4, in <listcomp>
    c = [i*j for i in a for j in b]
NameError: name 'b' is not defined

The reason has to do with how Python treats the outermost comprehension iterable differently. See https://stackoverflow.com/questions/13905741/accessing-class-variables-from-a-list-comprehension-in-the-class-definition. Note that the following does not give any errors when executed

class Test:
    a = [1, 2, 3]
    b = [1, 2, 3]
    c = [i for i in a]

asmeurer avatar Jan 09 '20 21:01 asmeurer

Actually it doesn't even catch the simpler case

class Test2:
    x = 1
    a = [x for i in range(2)]
$python test.py
Traceback (most recent call last):
  File "test.py", line 6, in <module>
    class Test2:
  File "test.py", line 8, in Test2
    a = [x for i in range(2)]
  File "test.py", line 8, in <listcomp>
    a = [x for i in range(2)]
NameError: name 'x' is not defined

asmeurer avatar Jan 10 '20 20:01 asmeurer

pretty sure pyflakes doesn't know at all about the ~special class scope -- but probably wouldn't be too difficult to add

asottile avatar Jan 10 '20 20:01 asottile

It gets it right for normal nested functions (i.e., methods)

class Test3:
    x = 1
    def func(self):
        print(x) # pyflakes gives an undefined name warning here

asmeurer avatar Jan 10 '20 20:01 asmeurer