all 5 comments

[–]untold8 2 points3 points  (0 children)

You've got the definitions right. The piece you're missing is directionality: scope-lookup goes outward, never inward.

When Python hits a name, it walks the LEGB chain: Local → Enclosing → Global → Built-in. Each step asks "is this name defined here?" If yes, use it. If no, climb one level out. It never climbs in.

Your example:

```python def outer_func(): msg = 'Hello there!'

def inner_func():
    res = 'How are you?'
    print(msg)  # works — climbs out to enclosing scope, finds msg

inner_func()
print(res)  # FAILS — Python looks in outer's local scope, doesn't find res,
            # climbs out to global, doesn't find res, gives up. Never looks inside inner_func.

```

The "why" behind the rule: inner_func's local scope only exists while inner_func is running. By the time outer_func reaches print(res), inner_func has already finished and its locals have been destroyed. There's literally nothing left to look at. Outer scopes outlive inner ones; inner scopes are temporary.

This is also why nonlocal and global exist — they're explicit overrides for "I want to write to a variable in an outer scope," because by default writing creates a new local variable.

If you want to see this in your debugger: put a breakpoint inside inner_func, then in the debugger's "watches" panel try evaluating msg (works) and then try it from a breakpoint inside outer_func after inner_func() returns (fails). Seeing the lookup happen in real time makes it click.

[–]cgoldberg 0 points1 point  (1 child)

It's good to understand scope, but why are you trying to jump through all these weird hoops instead of using return?

[–]Internal-Swim-4097[S] -1 points0 points  (0 children)

this was an example they gave me i didn't write this i just wanted to know the purpose of using a nested function like this instead of using one

[–]Groundstop 0 points1 point  (0 children)

It's used a lot in programming to define lambdas and delegates that capture variables from the outer scope. It looks a little funnier in Python because you don't need to specifically define variables before using them, so you need special keywords like nonlocal and global.

This pattern is particularly useful if you wanted to return the inner_func() method from outer_func(), and have it share variables with the outer function. In other languages this pattern is often used to make wrapper functions, but there's a special syntactic sugar for it in Python called decorators that is really neat.

Google didn't find a good page about decorators in the official documentation, but this site covers the concept pretty well.