[Python-ideas] Unify global and nonlocal

Nick Coghlan ncoghlan at gmail.com
Tue Feb 4 16:24:28 CET 2014


On 4 February 2014 11:23, Steven D'Aprano <steve at pearwood.info> wrote:
> In the case of globals and non-locals:
>
> * Non-locals always have an enclosing function, globals do not.
>
> * Non-locals and globals are typically used for different purposes,
>   by users at different levels of expertise. Writing to a non-local
>   scope using the nonlocal keyword tends to be done only by advanced
>   users for advanced purposes; writing to global variables using the
>   global keyword tends to be done only by beginners who haven't yet
>   learned that global variables are considered harmful.
>
> * A corrolary of the above is that it is difficult to think of any
>   use-cases where you don't know at edit-time whether you intend to
>   write to a variable in the global scope or a non-local scope. I can't
>   think of any case where I wouldn't know whether to declare something
>   global or nonlocal ahead of time, so there's no advantage to having a
>   single keyword handle both cases.

There's also a critical operational distinction: 'nonlocal' demands
that it be able to find the name at compile time, while 'global' will
happily create a *new* name binding at module global scope. This
difference in intent allows an appropriate error message to be
generated when nonlocal is used incorrectly:

    >>> def outer():
    ...     a_name = 1
    ...     def inner():
    ...         nonlocal a_nme
    ...         a_name += 2
    ...         return a_name
    ...     return inner
    ...
    SyntaxError: no binding for nonlocal 'a_nme' found

By contrast, global will happily bind new names, because the compiler
makes no assumptions about what names may eventually show up at module
global scope at run time:

>>> def f():
...     global a_name
...     a_name += 2
...     return a_name
...
>>> f()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 3, in f
NameError: global name 'a_name' is not defined
>>> a_name = 1
>>> f()
3

While the difference isn't often obvious, function namespaces are
actually *very* special beasts in Python, compared to the relatively
straightforward behaviour of module and the default class namespaces
as key:value mappings. This is reflected both in the additional
restrictions that apply to function namespaces (like not allowing star
imports in Python 3), as well as in the fact that they are accessed
via nonlocal, while the module namespace is accessed (for rebinding
purposes) via the global statement. It's also why mutating the mapping
returning by globals() is fully supported, while mutating the result
of locals() is explicitly declared as having undefined behaviour (it
may or may not affect the current scope either temporarily or
permanently, depending on implementation details).

Cheers,
Nick.

-- 
Nick Coghlan   |   ncoghlan at gmail.com   |   Brisbane, Australia


More information about the Python-ideas mailing list