0

I defined a simple Class and generated a dict from another one:

class TestClass1:
    d1 = {1:'11', 2:'22' , 3:'33'}
    d2 = {d1[i]:i for i in sorted(d1, reverse=True)}

and I got:

Traceback (most recent call last):
  File "C:\probe.py", line 1, in <module>
    class TestClass1:
  File "C:\probe.py", line 3, in TestClass1
    d2 = {d1[i]:i for i in sorted(d1, reverse=True)}
  File "C:\probe.py", line 3, in <dictcomp>
    d2 = {d1[i]:i for i in sorted(d1, reverse=True)}
NameError: name 'd1' is not defined

I added the second class to check if the second reference to the dictionary is okay, and it is okay:

class TestClass2:
    d1 = {1:'11', 2:'22' , 3:'33'}
    d2 = {i:i for i in sorted(d1, reverse=True)}

Curiously, there is NO the error in TestClass2.

Please, pay attention that the NameError occurs on d1[i] reference but does not on sorted(d1, reverse=True) which is in the same dictionary generator scope.

This is a similar question. However, I can not approve the explanation. The problem source could not be a different scope as the scope could not be different inside {} of the dictionary generator. It clearly shown in TestClass2 example where I remove the d1[i] reference but use d1 in sorted(d1, reversal=True). Both references are inside {} of the same dict generator.

How could it be explained?

wovano
  • 4,543
  • 5
  • 22
  • 49
Junk Qev
  • 1
  • 1
  • Comprehension bodies have their own scope, as if they were methods, and in this case python looks up names in the global scope rather than the class' scope. See the linked duplicate. – Andras Deak -- Слава Україні Nov 19 '22 at 14:34
  • 1
    Just to be precise, classes don't define a scope. The body defines a temporary *namespace* while being evaluated to define the class. – chepner Nov 19 '22 at 15:06
  • 1
    Aren't you surprised that the problem occurs for the first dict reference and does not for the second inside the same dictionary generator. I can not understand how Class namespace rules could define the different name definition inside one dictionary generator? – Junk Qev Nov 19 '22 at 15:12
  • The answer to the dupe quotes "_The scope of names defined in a class block is limited to the class block; it does not extend to the code blocks of methods_". The "`for x in thing`" part of comprehensions is like the signature of a function, evaluated immediately. Think default values for method kwargs. These are not part of "the code blocks of methods". At least if I understand correctly. This would mean `def foo(self, kwarg=d1)` would work, but referring to `d1` inside a method body would not. (I haven't checked.) – Andras Deak -- Слава Україні Nov 19 '22 at 15:17
  • I agree this example is more advanced/complex and the dupe does not satisfactory answer this question. I think it deserves a better answer including a reference to the standard in which the namespace / scoping rules are explained. – wovano Nov 25 '22 at 08:16

0 Answers0