0

Given the following ...

def foo(bar):
    return bar * 2

class FOO:
    BAR = 2
    a = foo(BAR)

    class FAZ:
        a = foo(BAR)

Why does python give a NameError: name 'BAR' is not defined error? My expectation was that it would work given that foo(BAR) is allowed and classes are allowed to refer to things outside their scope.

$ python foo.py
Traceback (most recent call last):
  File "foo.py", line 6, in <module>
    class FOO:
  File "foo.py", line 10, in FOO
    class FAZ:
  File "foo.py", line 11, in FAZ
    a = foo(BAR)
NameError: name 'BAR' is not defined

Is there a technical reason for this limitation? A design one?

Is there a workaround (aside from moving BAR outside the class)? i.e.,

BAR = 2                                                                         

class FOO:                                                                      
    BAR = BAR                                                                   
    a = foo(BAR)                                                                

    class FAZ:                                                                  
      a = foo(BAR)

Edit:

Anyone following the link to the duplicate:

At first glance, the question is somewhat different -- works in python2, not in python3 and is about list comprehensions. The accepted answer, however, seems to cover my question as well.

rrauenza
  • 6,285
  • 4
  • 32
  • 57
  • 1
    Because `BAR` must be referenced inside of `FOO`'s namespace, which *doesn't exist yet* since the class definition isn't finished executing. – juanpa.arrivillaga Jan 11 '18 at 22:33
  • @juanpa.arrivillaga `FOO.BAR` isn't available until after the class is finished ... but I see your point. `BAR` isn't a variable exactly. – rrauenza Jan 11 '18 at 22:34
  • Yep, edited my question after I looked at it again. Honestly, nested classes are rare in most of the Python code I've seen (with some important exceptions, e.g. `django` does stuff with inner classes) – juanpa.arrivillaga Jan 11 '18 at 22:35
  • Would it make more sense to have `FAZ` as a subclass instead of a nested one? – cs95 Jan 11 '18 at 22:35
  • Well, `BAR` is a variable that is in the class scope, which is sort of a special case in Python. Check out [this answer](https://stackoverflow.com/a/23471004/5014455) – juanpa.arrivillaga Jan 11 '18 at 22:36
  • @coldspeed Not if the nested class is `class Meta` in a Django model. Which it is .... – rrauenza Jan 11 '18 at 22:38
  • Maybe the question should be instead why does `a = foo(BAR)` work! But yeah, the scoping here is a little different than other languages. – rrauenza Jan 11 '18 at 22:43

0 Answers0