datarekha
Python Medium

What do the global and nonlocal keywords do, and when should you use them?

The short answer

global declares that a name inside a function refers to the module-level variable, allowing reassignment. nonlocal does the same for the nearest enclosing function scope. Both should be used sparingly — they make control flow harder to reason about, and a class or closure that returns a value is usually a cleaner design.

How to think about it

Both keywords sit on top of Python’s name-resolution order, LEGB — Local, Enclosing, Global, Built-in. By default, any name on the left of = inside a function becomes a new local for the whole body. global and nonlocal override that: they tell Python “don’t make a new local — rebind the one that already lives further out.”

Built-in   (len, print, …)

Global     (module level)        ← `global` targets here

Enclosing  (outer function)      ← `nonlocal` targets here

Local      (current function)    ← the default for any assignment

The follow-up interviewers actually care about is when not to use them — and the honest answer is “almost never; a class or a value-returning closure is usually cleaner.”

global — rebind a module-level name

_cache = {}

def fetch(key):
    global _cache
    if key not in _cache:
        _cache[key] = key.upper()     # a stand-in for an expensive lookup
    return _cache[key]

A subtlety worth stating: mutating _cache[key] = ... never needed global at all — mutation isn’t rebinding. You only need global if you intend to reassign the name itself (say _cache = {} to reset it); without it, that line would create a local shadow and leave the module cache untouched.

nonlocal — rebind an enclosing name

def make_counter(start=0):
    count = start                # lives in make_counter's frame

    def increment(step=1):
        nonlocal count           # rebind count in the enclosing frame
        count += step
        return count

    def reset():
        nonlocal count
        count = start

    def current():
        return count             # read-only — no nonlocal needed

    return increment, reset, current

inc, rst, cur = make_counter(10)
print("inc()  :", inc())
print("inc(5) :", inc(5))
print("cur()  :", cur())
rst()
print("after rst:", cur())

# Each call to make_counter gets its OWN frame — no shared state
c1_inc, _, c1_cur = make_counter(0)
c2_inc, _, c2_cur = make_counter(100)
c1_inc(); c1_inc(); c2_inc(50)
print("c1 =", c1_cur(), "c2 =", c2_cur())
inc()  : 11
inc(5) : 16
cur()  : 16
after rst: 10
c1 = 2 c2 = 150

increment and reset both rebind count in the enclosing frame, while current only reads it and so needs no declaration. And the last line is the reassuring part: two counters built from the same factory keep entirely separate state, because each make_counter call owns its own frame.

The cleaner alternatives

global and nonlocal are worth knowing but should make you pause before using. The same state usually reads better as:

  • a class__init__ plus methods; state is explicit and testable;
  • a returned value — the caller holds the state and your functions stay pure;
  • a mutable container in the enclosing scope — mutating a list or dict needs no nonlocal (just mind the mutable-default trap).

One mechanical difference to keep straight: nonlocal requires the name to already exist in an enclosing scope, while global can create a module-level name that didn’t exist yet.

Keep practising

All Python questions

Explore further

Skip to content