Code Reference

Scope and Namespaces

Python · Reference cheat sheet

Scope and Namespaces

Python · Reference cheat sheet


📋 Overview

Name lookup follows the LEGB rule: Local → Enclosing → Global → Built-in. Assignment creates bindings in the current scope unless global or nonlocal is declared. Each module and function has its own namespace.

🔧 Core concepts

ScopeWhere
LocalCurrent function
EnclosingOuter function(s) — closures
GlobalModule level
Built-inbuiltins module
global xBind / assign module name
nonlocal xRebind enclosing function name
Class bodyIts own namespace; methods don't see it as enclosing for LEGB

Comprehensions (3.x) have their own local scope for loop targets.

💡 Examples

LEGB:

len = 3  # shadows built-in — avoid!

def outer() -> None:
    x = "enclosing"

    def inner() -> None:
        print(x)  # enclosing

    inner()

outer()

global / nonlocal:

counter = 0

def bump_global() -> None:
    global counter
    counter += 1

def make_counter():
    n = 0

    def inc() -> int:
        nonlocal n
        n += 1
        return n

    return inc

Class vs instance:

class Demo:
    kind = "demo"

    def label(self) -> str:
        # 'kind' is not local; looked up on class via self/type
        return self.kind

print(Demo().label())

Inspect:

import builtins

def f(a: int = 1) -> None:
    b = 2
    print(locals())
    print("sum" in dir(builtins))

f()

⚠️ Pitfalls

  • Assignment anywhere in a function makes the name local for the whole function — easy UnboundLocalError.
  • Shadowing builtins (list, id, type) causes confusing bugs.
  • from module import * pollutes namespaces — avoid.
  • Class attributes vs instance attributes: mutable class attrs are shared.
  • Closures late-bind — see closures.

On this page