Python
Nested Functions
Closures
Programming
Python Functions

Why aren't python nested functions called closures?

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

Introduction

A nested function and a closure are related concepts, but they are not the same thing. A nested function is any function defined inside another function, while a closure is a nested function that captures variables from the enclosing scope and carries that state with it.

A Nested Function Is About Where It Is Defined

If one function is declared inside another, it is nested. That definition says nothing yet about captured state.

python
1def outer():
2    def inner():
3        return "hello"
4    return inner()
5
6print(outer())

Here inner is nested because it lives inside outer, but it does not retain any variable from the surrounding scope. So it is nested, but not a closure in the strict sense.

A Closure Captures Outer Variables

A closure appears when the inner function references a variable from the enclosing function and keeps access to it after the outer function has already returned.

python
1def make_multiplier(factor):
2    def multiply(x):
3        return x * factor
4    return multiply
5
6by_three = make_multiplier(3)
7print(by_three(10))

Output:

text
30

The returned function remembers factor even though make_multiplier has finished. That remembered binding is what makes it a closure.

Why the Distinction Matters

The distinction is useful because closures have behavior that ordinary nested functions do not. They can preserve state, act as factories, support decorators, and interact with nonlocal rebinding.

python
1def counter():
2    count = 0
3
4    def inc():
5        nonlocal count
6        count += 1
7        return count
8
9    return inc
10
11c = counter()
12print(c())
13print(c())

Without nonlocal, rebinding count inside inc would create a new local variable instead of updating the captured one.

Python Stores Captured State Explicitly

You can inspect a closure through the function's __closure__ attribute.

python
1def make_adder(base):
2    def add(x):
3        return base + x
4    return add
5
6adder = make_adder(5)
7print(adder.__closure__)
8print([cell.cell_contents for cell in adder.__closure__])

That output shows the captured values stored in closure cells. It is a concrete reminder that Python is preserving lexical state, not just nesting function definitions syntactically.

A Common Closure Gotcha

Closures capture names, not snapshots of loop variables. That is why this example surprises many people:

python
1funcs = []
2for i in range(3):
3    funcs.append(lambda: i)
4
5print([f() for f in funcs])

Output:

text
[2, 2, 2]

A common fix is default-argument binding:

python
1funcs = []
2for i in range(3):
3    funcs.append(lambda i=i: i)
4
5print([f() for f in funcs])

That forces the current loop value to be bound at definition time.

Why Not Call Every Nested Function a Closure?

Because doing so would erase an important semantic difference. A nested function may just be a local helper with no preserved state at all. A closure, by contrast, is specifically about captured environment.

That distinction becomes important as soon as you care about state persistence, rebinding behavior, or memory of outer variables after the outer function has returned.

Common Pitfalls

A common mistake is calling every nested function a closure even when no state capture happens. That hides the meaningful part of what a closure is.

Another issue is forgetting nonlocal when trying to rebind captured variables.

Developers also often assume closures capture the value of a loop variable immediately, when in fact they usually capture the name and resolve it later.

Summary

  • A nested function is defined inside another function.
  • A closure is a nested function that captures variables from an outer scope.
  • Every closure is nested, but not every nested function is a closure.
  • Closures preserve state after the outer function returns.
  • The distinction matters because captured state changes how the function behaves.

Related reading
Free course
Beginner
7 lessons
2 hours
Tackling System Design Interview Problems

A short course that equips you with the skills to approach system design interviews methodically.

Start the free course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

All Rights Reserved.