我在 Python 的循环里批量创建了一串函数,本以为每个都记着各自的循环值,结果调用时它们竟然全都返回了同一个最后的值,我排查了大半天的复盘

我在 Python 循环里用 lambda 批量创建了一串函数装进列表,本以为它们会分别返回 0、1、2,结果挨个调用竟全返回 2——循环的末值,每个函数都"失忆"了。深挖才懂:Python 闭包是"延迟绑定(late binding)"——lambda 捕获的不是"创建时 i 的值",而是"变量 i 本身"的引用,它取值发生在"被调用时"而非"被定义时";三个 lambda 共享同一个 i,循环结束 i 停在 2,之后调用谁都读到 2。我甚至在循环后手动把 i 改成 100,闭包返回值就跟着变 100,铁证它读的是变量不是快照。这篇从闭包捕获的是变量还是值讲起,到默认参数 lambda i=i/工厂函数/functools.partial 在创建时冻结值的正解、这坑在事件回调/调度/处理函数 map 里的伪装、与可变默认参数/

我在 Python 的循环里批量创建了一串函数,本以为每个都记着各自的循环值,结果调用时它们竟然全都返回了同一个最后的值,我排查了大半天的复盘

这是一个让我对 Python 闭包"看清真面目"的故事。我有个需求:根据一个列表,批量生成一串函数,每个函数,都应该"记住"它被创建时对应的那个值。我顺手写了个循环,在里面用 lambda 创建了这些函数,装进一个列表。逻辑看着天经地义。可当我挨个调用这些函数时,诡异的结果出现了:我本以为它们会分别返回 0, 1, 2,结果它们全都返回了 2——也就是循环的最后一个值!每一个函数,都"失忆"了,忘了自己当初对应的值,异口同声地报出了同一个数。

我当时百思不得其解:我明明是在每一轮循环里,用当时i 创建的函数啊,为什么它们记住的,不是各自创建时的 i,而是循环结束后那个最终的 i?我顺着这个反直觉的现象深挖,才终于揭开真相,补上了我对 Python 闭包一个最根本的认知漏洞:问题的核心,是 Python 的闭包,采用的是"延迟绑定(late binding)"。我一直想当然地以为,lambda: i 这个闭包,会在创建的那一刻,就"拍下" i 当时的值(比如 0)、把这个值"装进"自己肚子里;可真相是:闭包记住的,根本不是"创建时 i 的值",而是"i 这个变量本身"(对它的引用);它不在创建时取值,而是在被调用的那一刻,才去查看 i 当前的值而我的那些闭包,全都引用着同一个循环变量 i;当循环结束时,i 已经停在了它的最后一个值 2 上;所以,我之后无论调用哪个闭包,它们去查看 i 时,看到的都是那个最终值 2——于是,它们众口一词地,全返回了 2我这才痛彻地明白:Python 的闭包,捕获的是变量,而非值;它读取该变量的时机,是在调用时,而非定义时。这个"延迟绑定"的特性,本身并无对错,但它极其违反"闭包应该记住创建时的快照"这一普遍直觉;一旦在循环中批量创建闭包,就会掉进这个"所有闭包共享同一个循环变量、最终都只看到它的末值"的经典陷阱里。理解一门语言的闭包,到底捕获的是"值"还是"变量"、到底在"何时"求值,是绕不开的一道坎。

故障现场:循环里创建的闭包,全都共享同一个循环变量

我把这个"全返回 2"的现场,用代码摊开给你看:

# ✗ 灾难: 循环里创建闭包, 它们共享同一个循环变量 i
funcs = []
for i in range(3):
    funcs.append(lambda: i)   # ✗ 闭包捕获的是"变量 i", 不是"此刻 i 的值"

# 本以为: funcs[0]()=0, funcs[1]()=1, funcs[2]()=2
# 实际:
print(funcs[0]())   # ✗ 2
print(funcs[1]())   # ✗ 2
print(funcs[2]())   # ✗ 2  —— 全都是 2!

# 为什么全是 2?
#   - Python 闭包是"延迟绑定(late binding)":
#     闭包记住的是"变量 i 本身"(引用), 不是创建时 i 的值。
#   - 闭包"取 i 的值"发生在"被调用时", 而不是"被定义时"。
#   - 三个 lambda 都引用同一个 i; 循环结束后 i 停在 2。
#   - 所以之后调用任何一个, 去查 i, 看到的都是 2。

# 同样的坑也出现在 def 定义的函数、列表推导(旧 Python2)、回调注册等场景:
handlers = []
for evt in ["click", "hover", "drag"]:
    handlers.append(lambda: print(evt))   # ✗ 全部会打印 "drag"

# 验证一下"它读的是变量当前值":
i = 100
print(funcs[0]())   # ✗ 100! 改了 i, 闭包跟着变 —— 证明它读的是变量, 不是快照

# 根因: Python 闭包延迟绑定, 捕获变量而非值, 调用时才求值;
#   循环里批量创建的闭包共享同一循环变量, 最终都只看到它的末值。

看着这段代码,我才算彻底想明白了这场"全返回 2"的根源。问题的核心,是 Python 闭包的"延迟绑定(late binding)":lambda: i 捕获的,是"变量 i 本身"(引用),而不是"创建时 i 的值";它"取 i 的值"这个动作,发生在"被调用时",而不是"被定义时"于是:三个 lambda 都引用同一个 i;循环结束后,i 停在了 2;此后调用任何一个,它去查 i,看到的都是 2我还做了个验证:循环后手动把 i 改成 100,再调用 funcs[0](),它竟然返回 100!——这铁证如山地说明,闭包读的是变量的当前值,而不是某个时刻的快照这个坑,不只出现在 lambda:def 定义的函数、事件回调的批量注册(for evt in ... : ...lambda: print(evt) 全打印 "drag"),都会中招。归根结底:Python 闭包延迟绑定,捕获变量而非值、调用时才求值;循环里批量创建的闭包共享同一个循环变量,最终都只看到它的末值——这,就是根源。

第一件事:搞懂闭包捕获的是"变量"还是"值"

定位到根源,我必须把"闭包到底捕获了什么、何时求值"这件事,从根上彻底搞清楚:

Python 闭包: 捕获"变量"(引用), 调用时才求值(延迟绑定)

# 什么是闭包?
#   - 一个函数, 引用了它"外层作用域"里的变量, 就形成了闭包。
#   - 闭包让内层函数"记住"了外层的变量。

# 关键: 它记住的是"变量", 不是"值"!
#   - 闭包持有的是对外层变量的"引用"(绑定到那个变量名)。
#   - 求值时机 = "调用闭包时", 那时才去读变量的"当前值"。
#   - 这叫"延迟绑定 / late binding"。

# 所以循环里的坑:
#   - for i in range(3): funcs.append(lambda: i)
#   - 三个 lambda 共享同一个变量 i(循环变量在循环结束后依然存在且=末值)。
#   - 调用时都读 i 的当前值 → 全是 2。

# 反直觉点:
#   - 直觉以为"创建时就把值拍进闭包" → 其实是"调用时才去看变量"。
#   - 很多语言(JS 的 var 也有类似坑, let 才修复)都有这个历史包袱。

# 怎么判断会不会中招?
#   - 在"循环/会变化的作用域"里创建闭包, 且闭包引用了那个会变的变量 → 危险!
#   - 如果闭包立刻就被调用(不留到以后) → 不会中招(那时变量值还对)。

# 关键认知: 闭包捕获变量、调用时求值。
#   - 要"冻结"创建时的值, 必须主动把"值"在创建时就"拷贝/绑定"进去。

# 核心: Python 闭包捕获的是变量(引用)、在调用时才求值(延迟绑定);
#   循环里共享循环变量的闭包, 最终都读到末值, 要冻结值需在创建时主动绑定。

原理终于清晰了。什么是闭包?——一个函数,引用了它"外层作用域"里的变量,就形成了闭包,它让内层函数"记住"了外层的变量。关键在于:记住的是"变量",不是"值"!——闭包持有的,是对外层变量的"引用"(绑定到那个变量名);求值的时机,是"调用闭包时",那时才去读变量的当前值,这就叫"延迟绑定 / late binding"。所以循环里的坑就清楚了:三个 lambda 共享同一个变量 i(循环变量在循环结束后依然存在、且等于末值),调用时都读 i 的当前值,全是 2。反直觉的点在于:直觉以为"创建时就把值拍进闭包",其实是"调用时才去看变量"(很多语言都有这个历史包袱,比如 JS 的 var 也是,直到 let 才修复)。怎么判断会不会中招?在"循环/会变化的作用域"里创建闭包、且闭包引用了那个会变的变量,就危险;但如果闭包立刻就被调用(不留到以后),就不会中招(那时变量值还对)。由此,我刻下一个关键认知:闭包捕获变量、调用时求值;要"冻结"创建时的值,必须主动把"值"在创建时就拷贝/绑定进去。归根结底:Python 闭包捕获的是变量(引用)、在调用时才求值(延迟绑定);循环里共享循环变量的闭包,最终都读到末值,要冻结值需在创建时主动绑定。

第二件事:正解——在创建时就把值"冻结"进去

搞懂了原理,正解就清晰了:既然闭包捕获的是变量,那就在创建闭包的那一刻,主动把"当时的值"绑定进去,让每个闭包拥有自己的、独立的那个值。

# ✓ 正解一: 用默认参数, 在创建时就"求值并绑定"(最常用!)
funcs = []
for i in range(3):
    funcs.append(lambda i=i: i)   # ✓ 默认参数 i=i: 创建时就把当前 i 的值绑给参数 i
# 默认参数的值在"函数定义时"就被求值并固定下来 → 每个闭包有自己独立的 i
print(funcs[0](), funcs[1](), funcs[2]())   # ✓ 0 1 2

# ✓ 正解二: 用工厂函数, 每次调用产生一个新作用域
def make_func(x):
    return lambda: x      # x 是这次调用独有的局部变量, 互不干扰
funcs = [make_func(i) for i in range(3)]
print(funcs[0](), funcs[1](), funcs[2]())   # ✓ 0 1 2

# ✓ 正解三: functools.partial, 把参数"绑死"在创建时
from functools import partial
def show(x): return x
funcs = [partial(show, i) for i in range(3)]
print(funcs[0](), funcs[1](), funcs[2]())   # ✓ 0 1 2

# 为什么这些能解决?
#   - 它们都在"创建闭包的那一刻", 把"当前的值"捕获/拷贝/绑定下来。
#   - 默认参数: 定义时求值, 绑给参数(参数是闭包自己的局部变量)。
#   - 工厂函数: 每次调用 make_func 都开一个新作用域, x 各自独立。
#   - partial: 把实参在创建 partial 对象时就固定进去。
#   - 共同点: 从"引用一个共享的变量" → 变成"持有一个自己的值"。

# 现代提示: 列表推导/生成器里, Python3 的 i 作用域已隔离, 但
#   "循环里创建闭包留待以后调用"的坑依然存在 —— 仍需上面的写法。

# 核心: 在创建闭包时就把值冻结进去 —— 默认参数 lambda i=i / 工厂函数 / partial,
#   让每个闭包持有自己独立的值, 而不是共享同一个会变的变量。

修复的思路,统一而清晰:既然闭包捕获的是"变量",那就在创建时,主动把"值"绑进去,让每个闭包拥有自己独立的那份。正解一,默认参数(最常用!):lambda i=i: i——默认参数的值,在"函数定义时"就被求值并固定下来,绑给参数 i(参数是闭包自己的局部变量),于是每个闭包都有自己独立的 i正解二,工厂函数:make_func(i)——每次调用都开一个新作用域,里面的 x 是这次调用独有的局部变量,互不干扰。正解三,functools.partial:把实参在创建 partial 对象时就固定进去它们为什么都能解决?因为它们都在"创建闭包的那一刻",把"当前的值"捕获/拷贝/绑定了下来;共同点是——从"引用一个共享的、会变的变量",变成了"持有一个自己的、固定的值"(补充一个现代提示:Python 3 的列表推导/生成器里,i 的作用域已隔离,但"循环里创建闭包、留待以后调用"这个坑依然存在,仍需上面的写法。)归根结底:在创建闭包时就把值冻结进去——默认参数 lambda i=i / 工厂函数 / partial,让每个闭包持有自己独立的值,而不是共享同一个会变的变量。

第三件事:这个坑在真实代码里的几种伪装

这个"延迟绑定"的坑,在真实项目里,常常换一身马甲出现,我把它常见的伪装形态列了出来:

# 这个坑的几种"真实场景"伪装:

# 1. 循环里注册事件回调 / 按钮命令(GUI 最常见)
for name in ["A", "B", "C"]:
    button.on_click(lambda: handle(name))   # ✗ 点哪个都 handle("C")
    # ✓ button.on_click(lambda name=name: handle(name))

# 2. 循环里创建定时任务 / 调度
for cfg in configs:
    scheduler.add(lambda: run(cfg))          # ✗ 全跑最后一个 cfg
    # ✓ scheduler.add(lambda cfg=cfg: run(cfg))

# 3. 循环里构建 map: 名字 -> 处理函数
handlers = {}
for k in keys:
    handlers[k] = lambda: process(k)         # ✗ 全 process(最后一个 k)
    # ✓ handlers[k] = lambda k=k: process(k)

# 4. 异步任务里捕获循环变量
tasks = []
for url in urls:
    tasks.append(asyncio.create_task(fetch(url)))  # 这个 OK: 立刻求值传参
    # 但如果是 lambda: fetch(url) 留待以后 → 又中招

# 共同特征(一眼识别):
#   - "在循环里" + "创建了一个函数/闭包" + "这个函数留到以后才调用"
#   + "函数体里引用了循环变量" → 几乎必中招!

# 通用解法: 凡是循环里创建、延迟调用的闭包, 引用循环变量时
#   一律用默认参数 lambda x=x 把值当场冻结。

# 核心: 这坑常伪装成事件回调/调度任务/处理函数map等; 一眼识别法是
#   "循环里建闭包+延迟调用+引用循环变量"; 通用解法是默认参数当场冻结值。

这个坑的"马甲",我算是认全了。它最常出现在:循环里注册事件回调/按钮命令(GUI 重灾区,点哪个按钮都触发最后一个)、循环里创建定时/调度任务(全跑最后一个配置)、循环里构建"名字→处理函数"的 map(所有 key 都处理最后一个)、以及异步任务里捕获循环变量(若是 lambda 延迟调用就中招)。而识别它,有一个"一眼法":"在循环里" + "创建了一个函数/闭包" + "这个函数留到以后才调用" + "函数体里引用了循环变量"——这四个条件凑齐,就几乎必中招!(反过来,如果闭包是立刻求值、立刻传参的,比如 create_task(fetch(url))url 当场就传进 fetch 了,就没事。)而通用解法极其简单:凡是循环里创建、延迟调用、且引用循环变量的闭包,一律用默认参数 lambda x=x,把值当场冻结。归根结底:这坑常伪装成事件回调/调度任务/处理函数 map 等;一眼识别法是"循环里建闭包 + 延迟调用 + 引用循环变量";通用解法是默认参数当场冻结值。

下面这张图,是这次"闭包全返回末值"的成因与解法:

第四件事:三种修法的对比

这次踩坑后,我把"冻结闭包值"的三种修法,按可读性、适用场景比了一遍,方便对号入座。

修法 写法 优点 注意
默认参数 lambda i=i: ... 最简洁, 一行搞定 会让 lambda 多个参数, 别和真参数混淆
工厂函数 def make(x): return lambda: x 清晰、可读、能放复杂逻辑 多写几行, 但最易懂
functools.partial partial(fn, i) 函数式优雅, 适合已有函数 只能绑参数, 不能写额外逻辑
(反面) 直接 lambda: i lambda: i ✗ 延迟绑定, 全取末值

把它们排在一起,选择就清楚了。追求简洁,用默认参数 lambda i=i(一行搞定,但要注意它给 lambda 多加了个参数,别和真正的参数混淆);逻辑复杂、追求可读性,用工厂函数(多写几行,但最直观易懂,也能塞下复杂逻辑);已有现成函数、只是想绑参数,用 functools.partial(函数式优雅)。而那个反面写法 lambda: i,正是本文的祸根。我个人的偏好是:简单场景用默认参数(简洁),稍复杂或要给团队看的用工厂函数(可读性 > 炫技)这张表给我的启发是:同一个坑,往往有多种解法;但它们的内核是一致的——都是"把延迟求值的'变量引用',变成创建时就固定的'值捕获'";理解了内核,选哪种写法,就只是风格和场景的问题了

第五件事:Python 里其他"引用 vs 值/拷贝"的坑

这个闭包坑的本质,是"引用了同一个东西"。顺着这个本质,我把 Python 里其他几个同源的、关于"引用 vs 值/拷贝"的坑,一并排查了。

现象 正解
循环闭包延迟绑定 闭包全取循环变量末值 默认参数 lambda x=x 冻结值(本文)
可变默认参数 def f(x, lst=[]): 多次调用共享同一 list 默认 None, 函数内再 lst = lst or []
[[0]*3]*3 建二维数组 三行是同一个 list, 改一个全变 [[0]*3 for _ in range(3)]
浅拷贝嵌套对象 copy 后改嵌套, 原对象也变 copy.deepcopy 深拷贝
b = a 赋值"复制"列表 b 改了 a 也变(同一对象) b = a.copy() / list(a)
函数里改传入的可变参数 把调用方的 list/dict 改了 需要时先拷贝再改, 或返回新对象

这张表,让我看清了这些坑共同的根它们本质上是同一个问题:Python 里,变量、参数、默认值、乘法复制、赋值,很多时候操作的都是"对同一个对象的引用",而不是"独立的副本";一旦你以为自己有了好几个独立的东西、其实它们是同一个,改动一个就"牵一发而动全身",或者像本文这样,"共享一个会变的变量"。所以:可变默认参数(多次调用共享同一个 list)、[[0]*3]*3(三行是同一个 list)、浅拷贝改嵌套(原对象跟着变)、b = a 复制列表(其实是同一对象),全是这个根上长出来的。它们共同的启示是:写 Python,要时刻在脑子里分清"我现在拿到的,是一个'引用'(指向某个共享对象),还是一份'独立的拷贝'?"——需要独立时,就要显式地去拷贝/创建新的(deepcopy[... for ...]、默认参数冻结值);而不能想当然地以为"赋值/创建就等于复制"。看清"引用",是写对 Python 的一道分水岭。

第六件事:在循环里创建函数时,我现在会怎么决策

现在,每当我准备在循环里创建函数/闭包,脑子里都会过一遍这张决策图——核心就一问:这个闭包,会留到以后才调用、且引用了循环变量吗?

这张图的灵魂,是把判断聚焦到那个"四要素"上。第一问:闭包引用了循环变量吗?——没引用(只用常量/外部固定值),随便写,安全。第二问:它会留到以后才被调用吗?——如果当场就调用完了(变量值还对),也安全;只有当它引用了循环变量、又留作回调/任务/map 延迟调用时,才会落入延迟绑定陷阱一旦判定危险,就冻结值:追求简洁用默认参数 lambda x=x、要可读或有复杂逻辑用工厂函数、绑现成函数的参数用 partial这套判断,让我以后写循环里的闭包,不再凭感觉、而是有章可循——而它的核心,始终是那句:看清这个闭包,引用的是一个"会变的共享变量",还是一个"已被冻结的独立值"。

我立下的几条规矩

这场"闭包全返回末值"的事故,换来了我写 Python 时,刻进骨子里的几条铁律:

  1. Python 闭包是延迟绑定:捕获变量、调用时求值。它记的是变量本身,不是创建时的值——这是理解一切的前提。
  2. 循环里创建、延迟调用、引用循环变量的闭包,必冻结值。四要素凑齐就中招,一律用 lambda x=x 当场绑定。
  3. 默认参数是最常用的冻结手法。lambda i=i 简洁有效;复杂逻辑用工厂函数,绑现成函数用 partial。
  4. 警惕这坑的各种马甲。事件回调、调度任务、处理函数 map、异步任务——本质都是"循环里建闭包延迟调用"。
  5. 分清"引用"和"拷贝"。赋值/创建很多时候是共享同一对象的引用,需要独立就显式拷贝/创建。
  6. 同源的坑一起记。可变默认参数、[[0]*3]*3、浅拷贝——都是"以为独立其实共享"的引用问题。
  7. 不确定就立刻验证。写几行调用一下、或改掉变量再调,马上就能看出闭包读的是变量还是值。

附:几行代码彻底看清"延迟绑定"的真面目

口说无凭,这几个对比实验,能让你亲眼看清闭包延迟绑定的真面目,跑一遍胜过千言:

# 实验1: 证明"闭包读的是变量当前值, 不是创建时快照"
funcs = [lambda: i for i in range(3)]
print([f() for f in funcs])   # [2, 2, 2] —— 全是末值

i_outer = 0
def g():
    return lambda: i_outer
h = g()
print(h())        # 0
i_outer = 99      # 改外层变量
print(h())        # 99 ! —— 闭包跟着变, 铁证它读的是"变量"

# 实验2: 默认参数 vs 不用默认参数, 直接对照
bad  = [lambda: i for i in range(3)]
good = [lambda i=i: i for i in range(3)]
print([f() for f in bad])    # [2, 2, 2]   ✗
print([f() for f in good])   # [0, 1, 2]   ✓

# 实验3: 用 __defaults__ 看默认参数确实"创建时就固定了值"
fs = [lambda i=i: i for i in range(3)]
print([f.__defaults__ for f in fs])   # [(0,), (1,), (2,)] —— 每个闭包各存了自己的值!

# 实验4: 立即调用就不中招(对比, 理解"延迟"二字)
results = [(lambda: i)() for i in range(3)]   # 创建后立刻调用
print(results)   # [0, 1, 2] —— 立刻求值时 i 还是当前值, 所以是对的

# 核心: 实验证明 —— lambda: i 读的是变量(改 i 它跟着变, 留到最后全取末值);
#   lambda i=i 把值存进了 __defaults__(创建时就冻结); 立即调用则不受延迟绑定影响。

这几个实验,把"延迟绑定"这个抽象概念,变成了肉眼可见的事实实验 1 最有冲击力:闭包创建后,我在外面把变量改成 99,闭包的返回值竟然跟着变成了 99——这无可辩驳地证明,它读的是"变量"(那个会变的盒子),而非"创建时的快照"。实验 2lambda: ilambda i=i 直接对照,[2,2,2][0,1,2] 的差别一目了然。实验 3 最为精妙:我用 f.__defaults__ 把每个闭包的默认参数掏出来看,赫然是 [(0,), (1,), (2,)]——每个闭包,都在自己肚子里,存了一份属于自己的、创建时就固定下来的值!这就从机制上解释了默认参数为什么能解决问题。实验 4 则反过来印证:创建后立刻调用,结果是对的 [0,1,2],因为那一刻 i 的值还没变——这让"延迟"二字,有了最直观的注脚。这,正是我想用这几行代码,留给每一个 Python 学习者的最后一课:当你对一个语言特性的行为感到困惑或"反直觉"时,不要停留在猜测和争论——写几行最小的实验代码,让语言自己把真相演示给你看。那些通过亲手实验、亲眼所见而获得的认知,远比任何文字描述,都来得牢固和深刻。

写在最后

回头看,这场由"循环里的闭包"引发的、所有函数异口同声返回末值的事故,真正教给我的,是一个比"用默认参数冻结值"本身更深的道理:编程语言里,最容易咬人的,往往不是那些"明显复杂"的特性,而是那些"看起来简单、却和你的直觉悄悄相左"的细节"闭包记住了一个变量"——这句话,听起来朴实无华、理所当然;可"记住的是变量、而非,且在调用时才去看它"这个精确的语义,却和我"它应该记住创建时那一刻的快照"的朴素直觉,差了十万八千里——而这毫厘之差,就是那个让我所有函数都"失忆"的千里之谬。所以,真正学懂一门语言,不能停留在"我大概知道它是干嘛的"这种模糊的直觉,而要去较真它"究竟在何时、对什么、做了什么"的精确语义:它捕获的是值还是引用?它在定义时求值还是调用时求值?它复制的是对象还是引用?——这些"较真"出来的精确认知,平时看似吹毛求疵,却恰恰是在关键时刻,把你和那些诡异 bug 隔开的护城河真正的高手,与新手的差别,常常就在于是否愿意、并有能力,去抠清楚这些"看似简单"之处的精确语义对"想当然"保持警惕,对"精确语义"保持较真——这,是我用一次"闭包失忆"的事故,换来的、关于 Python、也关于"如何真正学懂一门语言"的、最朴素也最深刻的领悟。如果这篇复盘,能让你在下一次于循环里写下 lambda 时,心里"咯噔"一下、多问一句"它捕获的到底是变量还是值",那我对着那串全返回 2 的函数熬的这大半天,就值了。

—— 别看了 · 2026
声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理 邮箱1846861578@qq.com。
技术教程

我做的 AI Agent 跑长任务时跑着跑着就开始报上下文超长、回答还越来越糊涂,我对着疯狂飙升的 token 账单排查了大半天才搞懂上下文得管理的复盘

2026-6-2 2:17:52

技术教程

我把对象的方法当回调传给了 setTimeout,结果一执行就报 this 是 undefined、方法里的属性全访问不到,我对着这个丢了 this 的方法排查了大半天的复盘

2026-6-2 2:29:00

0 条回复 A文章作者 M管理员
    暂无讨论,说说你的看法吧
个人中心
购物车
优惠劵
今日签到
有新私信 私信列表
搜索