4

previously I thought that when we define a function, the function can be wrong, but python will not check it until it got executed:

x = 100

def f():
    x = 1/0
    return x

print(x)
# >>> 100

however, when I was learning the nonlocal statement

x = 100

def f():
    def g():
        nonlocal x
        x = x * 99
        return x
    return g

print(x)
# >>> SyntaxError: no binding for nonlocal 'x' found

It got checked out even if the function is not executed.

Is there anywhere I can find the official explanation for this?

Additional for variable bounding situation:

x = 100
def f():
    global x
    global xx
    x = 99
    return x

print(f())
# >>> 99
print(x)
# >>> 99

it seemed totally fine, if I global some variable that does not exist at all? And it doesn't even bring any error even if I execute this function?

this part is moved to a new individual question: Why am I able to global a non-existing varlable in python

jxie0755
  • 1,682
  • 1
  • 16
  • 35
  • nonlocal means the name exists in an outer lexical function scope, In above example outer lexical function scope is f() because of that you are getting no binding exception. more details - https://stackoverflow.com/questions/8050502/pythons-nonlocal-depends-on-level-of-hierarchy – MONTYHS Jul 11 '18 at 14:10
  • @MONTYHS I do know what does `nonlocal` do, I am simply questioning why this got checked when the function is not executed – jxie0755 Jul 11 '18 at 14:11

1 Answers1

3

The nonlocal checks the nearest enclosing scope, excluding globals (that is, module level variables). That is, your f() function should declare a x for it to work, as nonlocal can't see the global x = 100 variable.

See https://docs.python.org/3/reference/simple_stmts.html#the-global-statement.

As to why the error is raised without running the function, it is because the variable names are bound at compile-time, so it doesn't matter that you don't use this function at all. See https://docs.python.org/3/reference/executionmodel.html#resolution-of-names

However, global has different behaviour. Just like nonlocal if the global x already exists, it is used instead of the local one. However, if it doesn't, it means "if I create a variable named x, create it on the global scope, instead of the function scope". So, in your example

x = 100
def f():
    global x
    global xx
    x = 99
    xx = 123
    return x

print(f()) # 99
print(x)   # 99
print(xx)  # 123

a xx variable has appeared in the global namespace. It is only a hint to the compiler though, so if you declared global xx without assigning it, and try to print(xx) later, you still get a NameError for using an undefined variable

blue_note
  • 27,712
  • 9
  • 72
  • 90
  • I understand what does `nonlocal` do, but I am more interested why this got checked when I do not run this function at all. – jxie0755 Jul 11 '18 at 14:09
  • @Code_Control_jxie0755: sorry, I mis-read the question, will edit answer – blue_note Jul 11 '18 at 14:12
  • @Code_Control_jxie0755: edited – blue_note Jul 11 '18 at 14:18
  • so this is happening because it check all the variables bounding, but most of the time, if the variable is not found before, it will be assumed as a new variable creation, so that nothing will go wrong. But in this case, the `nonlocal` is suggesting "Do not create a new variable, but to look for an existing one to bound", and that will cause the problem. Am I understanding this corretly? – jxie0755 Jul 11 '18 at 14:27
  • @Code_Control_jxie0755: exactly. And this happens before the program runs – blue_note Jul 11 '18 at 14:30
  • But this does not explain the `global` statement?? Please refresh to see my edited question, I added another part for `global`. – jxie0755 Jul 11 '18 at 14:31
  • ok, i updated it – jxie0755 Jul 11 '18 at 14:35
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/174818/discussion-between-code-control-jxie0755-and-blue-note). – jxie0755 Jul 11 '18 at 14:39