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

循环生成异步函数时为何错误绑定外层作用域变量?如何修复?

问题原因

这是Python闭包的迟绑定特性导致的:闭包内部引用的外层变量,并不是在函数定义时就固定下来,而是等到函数被调用时,才会去外层作用域查找该变量的当前值。

你在for循环里生成async函数时,每个coro都引用了同一个param变量。循环结束后,param的值已经变成了最后一个元素9,所以当你后续调用所有coro()时,它们都会取到9这个值,输出自然都是81。

解决方法

这里有几种靠谱的解决方式:

1. 利用函数默认参数绑定值

在定义coro时,把param作为默认参数传入,默认参数会在函数定义时就计算并绑定当前值:

import asyncio

coroutines = []
for param in (1, 3, 5, 7, 9):
    # 用默认参数绑定当前循环的param值
    async def coro(current_param=param):
        print(current_param ** 2)
    
    coroutines.append(coro)

# 正确的异步运行方式:一次性运行所有协程
async def main():
    await asyncio.gather(*[coro() for coro in coroutines])

asyncio.run(main())

2. 使用工厂函数生成协程

写一个专门的工厂函数,每次调用时传入当前的param,返回绑定了该值的协程函数:

import asyncio

def create_coro(param):
    async def coro():
        print(param ** 2)
    return coro

coroutines = []
for param in (1, 3, 5, 7, 9):
    coroutines.append(create_coro(param))

async def main():
    await asyncio.gather(*[coro() for coro in coroutines])

asyncio.run(main())

3. 使用functools.partial绑定参数

借助functools.partial把当前的param绑定到协程函数上:

import asyncio
from functools import partial

async def coro(param):
    print(param ** 2)

coroutines = []
for param in (1, 3, 5, 7, 9):
    # 绑定当前param到coro的参数上
    bound_coro = partial(coro, param)
    coroutines.append(bound_coro)

async def main():
    await asyncio.gather(*[coro() for coro in coroutines])

asyncio.run(main())

另外注意:你原来的代码里用for coro in coroutines: asyncio.run(coro())是不合适的,因为每次asyncio.run都会创建一个新的事件循环,正确的做法是用asyncio.gather在一个事件循环里运行所有协程,上面的示例已经修正了这个问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 15:15:56