26

In Python 3.3.1, this works:

i = 76

def A():
    global i
    i += 10

print(i) # 76
A()
print(i) # 86

This also works:

def enclosing_function():
    i = 76
    def A():
        nonlocal i
        i += 10

    print(i) # 76
    A()
    print(i) # 86

enclosing_function()

But this doesn't work:

i = 76
def A():
    nonlocal i # "SyntaxError: no binding for nonlocal 'i' found"
    i += 10

print(i)
A()
print(i)

The documentation for the nonlocal keyword states (emphasis added):

The nonlocal statement causes the listed identifiers to refer to previously bound variables in the nearest enclosing scope.

In the third example, the "nearest enclosing scope" just happens to be the global scope. So why doesn't it work?

PLEASE READ THIS BIT

I do notice that the documentation goes on to state (emphasis added):

The [nonlocal] statement allows encapsulated code to rebind variables outside of the local scope besides the global (module) scope.

but, strictly speaking, this doesn't mean that what I'm doing in the third example shouldn't work.

Karl Knechtel
  • 62,466
  • 11
  • 102
  • 153
qntm
  • 4,147
  • 4
  • 27
  • 41
  • 8
    Your reasoning is completely understandable. Unfortunately, sometimes (just as in many languages), some things just are the way they are, either because of backward compatibility concerns or implementation difficulties or community voting or whatever. In this case, I think that the documentation should state more strongly that `nonlocal` *specifically excludes* the global scope. Then you're free to disagree whether that was a good choice, but at least it would be unambiguous. – John Y Jun 02 '13 at 14:39

5 Answers5

13

The search order for names is LEGB, i.e Local, Enclosing, Global, Builtin. So the global scope is not an enclosing scope.

EDIT

From the docs:

The nonlocal statement causes the listed identifiers to refer to previously bound variables in the nearest enclosing scope. This is important because the default behavior for binding is to search the local namespace first. The statement allows encapsulated code to rebind variables outside of the local scope besides the global (module) scope.

Mike Müller
  • 82,630
  • 20
  • 166
  • 161
  • 2
    Why not? It encloses everything. – qntm Jun 02 '13 at 00:45
  • 3
    Because http://docs.python.org/3/reference/simple_stmts.html#nonlocal says: "The statement [`nonlocal`] allows encapsulated code to rebind variables outside of the local scope **besides** the global (module) scope." (emphasis added) – Mike Müller Jun 02 '13 at 10:28
  • 1
    +1. Also it might be interesting noting that `nonlocal` was added to make Python's nested functions work more like canonical ("functional") closures. It's kind of a patch, and not as elegant as Javascript's or Scheme's closure scoping. What I'd like to know is **why is a module's scope considered global and not an enclosing one?** It's still not *global* to other modules (well, unless you do `from module import *`), is it? – Nadir Sampaoli Jun 02 '13 at 11:02
  • 1
    Nadir: yes, that's basically what I was asking as well. – qntm Jun 02 '13 at 13:00
  • 2
    In my opinion `global` should not be used at all, except for some very exceptional cases like embedding in C where I used it once. There is always a solutions without `global` if you only try hard enough and your code will be better. So making `nonlocal` reaching out to the global scope would have been a mistake in my opinion. – Mike Müller Jun 04 '13 at 01:47
4

why is a module's scope considered global and not an enclosing one? It's still not global to other modules (well, unless you do from module import *), is it?

If you put some name into module's namespace; it is visible in any module that uses module i.e., it is global for the whole Python process.

In general, your application should use as few mutable globals as possible. See Why globals are bad?:

  • Non-locality
  • No Access Control or Constraint Checking
  • Implicit coupling
  • Concurrency issues
  • Namespace pollution
  • Testing and Confinement

Therefore It would be bad if nonlocal allowed to create globals by accident. If you want to modify a global variable; you could use global keyword directly.

  • global is the most destructive: may affect all uses of the module anywhere in the program
  • nonlocal is less destructive: limited by the outer() function scope (the binding is checked at compile time)
  • no declaration (local variable) is the least destructive option: limited by inner() function scope

You can read about history and motivation behind nonlocal in PEP: 3104 Access to Names in Outer Scopes.

jfs
  • 399,953
  • 195
  • 994
  • 1,670
  • On one hand it makes sense to limit the behaviour scope of `nonlocal` not to intersect `global`'s («There should be one-- and preferably only one --obvious way to do it»). On the other side, this kind of feels inconsistent: «Special cases aren't special enough to break the rules». `global` seems a special case of `nonlocal`, to me. Though you could argue it's not, because you can import names from the module scope but not from an "enclosing", function-level scope. Python's great, but the way it handles scoping is tricky, at best. – Nadir Sampaoli Jun 03 '13 at 09:20
  • 2
    @NadiRSampaoli: I don't see how your comment is related to my answer that says: globals are bad therefore it would be bad if nonlocal could create a global by accident. – jfs Jun 03 '13 at 10:23
  • It's slightly related. IMO nonlocal's behavior is separated from global because it would be redundant, not because of "globals' evilness". You say «globals are bad therefore it would be bad if nonlocal could create a global by accident». First: how is it *by accident*? Second: "accident" is disregarded in Python (Guido would say: «we're all consenting adults here»). Third: a more sensible statement would be «globals are bad therefore it would be better if there weren't globals». But this would still go against Guido's «we're all adults», not allowing us to make our choices. – Nadir Sampaoli Jun 03 '13 at 10:45
3

It depends upon the Boundary cases:

nonlocals come with some senstivity areas which we need to be aware of. First, unlike the global statement, nonlocal names really must have previous been assigned in an enclosing def's scope when a nonlocal is evaluated or else you'll get an error-you cannot create them dynamically by assigning them anew in the enclosing scope. In fact, they are checked at function definition time before either or nested function is called

>>>def tester(start):
      def nested(label):
         nonlocal state   #nonlocals must already exist in enclosing def!
         state = 0
         print(label, state)
      return nested
SyntaxError: no binding for nonlocal 'state' found

>>>def tester(start):
      def nested(label):
          global state   #Globals dont have to exits yet when declared
          state = 0      #This creates the name in the module now
          print(label, state)
      return nested

>>> F = tester(0)
>>> F('abc')
abc 0
>>> state
0

Second, nonlocal restricts the scope lookup to just enclosing defs; nonlocals are not looked up in the enclosing module's global scope or the built-in scope outside all def's, even if they are already there:

for example:-

>>>spam = 99
>>>def tester():
      def nested():
         nonlocal spam  #Must be in a def, not the module!
         print('current=', spam)
         spam += 1
      return nested
SyntaxError: no binding for nonlocal 'spam' found

These restrictions make sense once you realize that python would not otherwise generally know enclosing scope to create a brand-new name in. In the prior listing, should spam be assigned in tester, or the module outside? Because this is ambiguous, Python must resolve nonlocals at function creation time, not function call time.

Praneeth
  • 902
  • 2
  • 11
  • 25
  • "These restrictions make sense once you realize that python would not otherwise generally know enclosing scope to create a brand-new name in" - I'm confused on this because the Python interpreter must track enclosing scope for each function because you don't need to use the nonlocal keyword to access the values of names in the enclosing scope. For instance def test1(x): def test2(): print(x) should just work. – Campbell Hutcheson Mar 14 '22 at 04:52
2

The answer is that the global scope does not enclose anything - it is global to everything. Use the global keyword in such a case.

Marcin
  • 48,559
  • 18
  • 128
  • 201
0

Historical reasons

In 2.x, nonlocal didn't exist yet. It wasn't considered necessary to be able to modify enclosing, non-global scopes; the global scope was seen as a special case. After all, the concept of a "global variable" is a lot easier to explain than lexical closures.

The global scope works differently

Because functions are objects, and in particular because a nested function could be returned from its enclosing function (producing an object that persists after the call to the enclosing function), Python needs to implement lookup into enclosing scopes differently from lookup into either local or global scopes. Specifically, in the reference implementation of 3.x, Python will attach a __closure__ attribute to the inner function, which is a tuple of cell instances that work like references (in the C++ sense) to the closed-over variables. (These are also references in the reference-counting garbage-collection sense; they keep the call frame data alive so that it can be accessed after the enclosing function returns.)

By contrast, global lookup works by doing a chained dictionary lookup: there's a dictionary that implements the global scope, and if that fails, a separate dictionary for the builtin scope is checked. (Of course, writing a global only writes to the global dict, not the builtin dict; there is no builtin keyword.)

Theoretically, of course, there's no reason why the implementation of nonlocal couldn't fall back on a lookup in the global (and then builtin) scope, in the same way that a lookup in the global scope falls back to builtins. Stack Overflow is not the right place to speculate on the reason behind the design decision. I can't find anything relevant in the PEP, so it may simply not have been considered.

The best I can offer is: like with local variable lookup, nonlocal lookup works by determining at compile time what the scope of the variable will be. If you consider builtins as simply pre-defined, shadow-able globals (i.e. the only real difference between the actual implementation and just dumping them into the global scope ahead of time, is that you can recover access to the builtin with del), then so does global lookup. As they say, "simple is better than complex" and "special cases aren't special enough to break the rules"; so, no fallback behaviour.

Karl Knechtel
  • 62,466
  • 11
  • 102
  • 153