You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python闭包底层实现机制深度问询:基于字节码指令的原理剖析

Python闭包的底层实现机制详解

Great question—let’s dive deep into how Python handles closures under the hood, using your code and bytecode snippets as our guide.

First, let's recap your example code for context:

def closure_test():
    x = 1
    def closure():
        nonlocal x
        x = 2
        print(x)
    return closure
closure_test()()

1. How does Python capture outer function local variables?

When Python compiles closure_test, it detects that the nested function closure references the outer local variable x (the nonlocal declaration makes this explicit, but even a read-only reference would trigger the same logic). Instead of storing x in closure_test's regular local variable stack, Python wraps x in a cell object.

Look at the key bytecode lines from closure_test:

2           0 LOAD_CONST               1 (1)
            2 STORE_DEREF              0 (x)

Instead of the standard STORE_FAST used for regular locals, we see STORE_DEREF—this tells us x is being stored in a cell object, not the function's local stack frame.

Next, when creating the nested closure function, these critical instructions handle the capture:

3           4 LOAD_CLOSURE             0 (x)
            6 BUILD_TUPLE              1
            8 LOAD_CONST               2 (<code object closure at 0x7f14ac3b9500, file "<string>", line 3>)
           10 LOAD_CONST               3 ('closure_test.<locals>.closure')
           12 MAKE_FUNCTION            8 (closure)
  • LOAD_CLOSURE: Pushes the cell object for x onto the stack
  • BUILD_TUPLE: Packages all captured cell objects into a tuple (here, just one for x)
  • MAKE_FUNCTION: Creates the new function object, passing the cell tuple as its closure environment (the 8 flag indicates the function carries a closure)

In short: Python identifies when a nested function references outer variables, wraps those variables in cells, and passes references to those cells to the nested function.

2. Where are captured variables stored?

Captured variables (the cell objects) are bound directly to the closure function. You can inspect this via the function's __closure__ attribute:

func = closure_test()
print(func.__closure__)  # Output looks like (<cell at 0x...: int object at 0x...>,)
print(func.__closure__[0].cell_contents)  # Initially 1, becomes 2 after calling func()

Each cell has a cell_contents attribute that holds the variable's actual value. The cell's lifecycle is tied to the closure function—even after closure_test finishes executing and its stack frame is destroyed, the cell persists as long as the closure exists. This is why closures can retain and modify state after the outer function exits.

3. How does the closure access these variables?

Looking at the closure function's bytecode:

5           0 LOAD_CONST               1 (2)
            2 STORE_DEREF              0 (x)

6           4 LOAD_GLOBAL              0 (print)
            6 LOAD_DEREF               0 (x)
            8 CALL_FUNCTION            1

We use two closure-specific instructions here:

  • LOAD_DEREF: Fetches the cell object at index 0 from the closure's cell tuple, then reads its cell_contents value
  • STORE_DEREF: Finds the same cell object and writes the new value to its cell_contents

Unlike LOAD_FAST/STORE_FAST (used for regular locals), these instructions are purpose-built to interact with the closure's cell-based environment.

Quick summary of the full flow

  1. When compiling the outer function, Python wraps referenced local variables in cell objects, using STORE_DEREF to store values
  2. When creating the closure, LOAD_CLOSURE and BUILD_TUPLE package cells into a tuple, which is passed to the new function via MAKE_FUNCTION
  3. The closure holds a reference to this cell tuple in its __closure__ attribute
  4. When the closure runs, LOAD_DEREF and STORE_DEREF read/write the cell_contents of the appropriate cell, enabling access and modification of the captured variable

This design also lets multiple closures share the same cell object (e.g., if the outer function returns multiple nested functions referencing the same variable), which is how closures can share state with each other.

内容的提问来源于stack exchange,提问作者akm

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.28 09:32:42