Gyaan

LEGB Scope Rule

beginner scope LEGB namespace global local

When we use a variable name, Python needs to figure out what it refers to. It searches through four scopes in a specific order: L → E → G → B. The first match wins.

B — Built-in Scope
print, len, range, int, str...
G — Global Scope
x = "global"
E — Enclosing Scope
y = "enclosing"
L — Local Scope
z = "local"
lookup: L → E → G → B

Local Scope

Variables created inside a function are local. They exist only while the function runs and can’t be accessed from outside.

def greet():
    message = "hello"  # local to greet()
    print(message)

greet()          # hello
print(message)   # NameError: name 'message' is not defined

Enclosing Scope

When we have nested functions, the inner function can access variables from the outer (enclosing) function.

def outer():
    name = "Manish"       # enclosing scope for inner()

    def inner():
        print(name)       # found in enclosing scope

    inner()

outer()  # Manish

Global Scope

Variables defined at the module level (outside any function). Accessible everywhere in the file.

counter = 0  # global

def increment():
    global counter   # tell Python we mean the global one
    counter += 1

increment()
print(counter)  # 1

Without the global keyword, Python would treat counter as a new local variable and throw an UnboundLocalError when we try to += it.

Built-in Scope

This is where Python’s built-in functions live — print, len, range, int, str, etc. We can technically override them (please don’t).

# Don't do this — but it shows how scope works
print = "oops"    # shadows the built-in print
print("hello")    # TypeError: 'str' object is not callable

The global Keyword

Lets us modify a global variable from inside a function. Without it, assigning to a variable inside a function creates a new local one.

x = 10

def change():
    global x
    x = 20

change()
print(x)  # 20

The nonlocal Keyword

Same idea, but for enclosing scope. Lets an inner function modify a variable from the outer function.

def counter():
    count = 0

    def increment():
        nonlocal count  # modify the enclosing variable
        count += 1
        return count

    return increment

c = counter()
print(c())  # 1
print(c())  # 2

In simple language, when Python sees a variable name, it checks four places in order: the current function, any enclosing functions, the module level, and finally the built-ins. First match wins. Use global and nonlocal when we need to write to an outer scope — but use them sparingly.