当前位置: 首页 > news >正文

Python小记:星号解包的妙用

最近在学习 Python asyncio,过程中遇到一段代码:

await asyncio.gather(*(generate_random(num) for num in values))

初看这段代码就有一种熟悉的感觉,但是太久没有写 Python,并没有立刻反应过来 * 在这里到底在做什么。再三思考之后才回忆起来:这里的 * 是迭代器解包(iterable unpacking),把生成器表达式产出的多个值解包成多个独立参数,再传递给外层调用函数。写下这篇文章做个记录,方便以后温故知新。


为了真正理解 *,先来看一个基础的场景。假设有一个函数需要接收多个位置参数:

def demo(a, b, c):print(a, b, c)

如果已经有一个可迭代对象,比如一个列表:

values = [1, 2, 3]

那么下面两种写法是等价的:

demo(*values)   # 1 2 3
demo(1, 2, 3)   # 1 2 3

这里 * 的作用就是:把可迭代对象"拆开",变成多个独立的位置参数再传进去。

import asyncio
import randomasync def main():values = [1, 2, 3]await asyncio.gather(*(generate_random(num) for num in values))async def generate_random(num):print(f"{num} random number is {random.uniform(0.1, 1.0)}")await asyncio.sleep(2)if __name__ == "__main__":import timestart = time.perf_counter()random.seed(49)asyncio.run(main())end = time.perf_counter()print(f"\n==> Total time: {end - start:.2f} seconds")

如果不是生成器而是列表,那么星号能否起作用呢?答案是可以的。上面的代码也可以写成列表推导式:

await asyncio.gather(*[generate_random(num) for num in values])

两种写法在运行结果上没有区别,不过有一个点要留意:生成器表达式是惰性的。

  • 列表推导式会一次性把所有对象生成出来,先构建一个完整列表;
  • 生成器表达式则是每次迭代时才真正创建对象。

asyncio.gather 中,无论使用生成器表达式还是列表推导式,所有协程都会并发执行,生成器的惰性特质主要体现在内存使用上。当 values 数量比较多或者 generate_random 函数运行比较耗时(比如涉及 I/O)的情况下,生成器不会一次性占用大量内存,这个特质作用就会很大。


最后小结

总体来看 * 不只是"不定参数",还可以用来做可迭代对象/列表的解包。在使用 asyncio.gather 时,* 可以将生成器表达式或列表推导式产生的多个协程对象解包为独立参数传递给 gather 函数,实现并发执行。

附参考

  • Python's asyncio: A Hands-On Walkthrough https://realpython.com/async-io-python/
http://www.jsqmd.com/news/972876/

相关文章:

  • 百度地图BMap避坑指南:Vue项目中多个标记点(info-window)点击冲突的完美解决方案
  • 告别WebUI:用Postman玩转服务器BMC的12个Redfish高频操作(含Session管理避坑)
  • 2025量子AI实战指南:从云API调用到业务增效的三天落地路径
  • Pluto SDR新手避坑指南:从MATLAB驱动安装到第一个信号收发成功
  • AI Orchestration:MuleSoft与LangChain的企业级协同架构
  • Vivado FIFO IP核仿真全流程:从Testbench编写到波形分析实战
  • 别再当‘炼丹师’了!用SHAP和LIME给你的机器学习模型做个‘X光’检查
  • 从抓包到内核参数:图解NAT环境下TCP连接被RST的完整诊断流程(以F5+LVS为例)
  • 告别手动输入!一招搞定SAP业务伙伴(BP)与供应商主数据的自动同步(附SPRO路径截图)
  • 别再手动装依赖了!ROS 2新手必看的rosdep保姆级使用指南(附package.xml避坑要点)
  • 3步掌握哔哩下载姬:B站视频批量下载与高级格式支持完全指南
  • UG NX 12 建模效率翻倍!点构造器这3个隐藏用法,90%新手都不知道
  • 遗传算法工程化实战:适应度设计、算子适配与收敛诊断
  • 用贝叶斯+正态分布反推新冠感染时间的实操建模
  • pandas多维聚合实战:从风控指标到BI报表的稳定计算方案
  • 电商搜索排序选型:DNNs与树模型实战权衡指南
  • 从音频均衡器到5G滤波器:手把手拆解幅频/相频特性在真实项目里的应用
  • 数据科学求职通关:知识如何转化为可验证的交付能力
  • 别再乱用SysTick了!STM32CubeMX配置FreeRTOS信号量时,这个时基坑你踩过吗?
  • MATLAB零配置调用RefProp查水物性:含64位接口rp_proto64和refpropm函数
  • Dense X Retrieval:RAG中稠密检索与交叉编码器重排序的工程实践
  • 模板驱动文档自动化:从填空题到智能生成
  • MuleSoft如何实现企业级LLM工作流编排与治理
  • 别再只换刷机包了!创维E900V21C线刷卡2%的真正元凶与排查指南
  • 告别Electron?用Flutter 3.0从零构建你的第一个Windows桌面应用(附VS2019避坑指南)
  • 告别闪退!用Maven Assembly Plugin和exe4j打包JavaFX应用(附JRE配置避坑指南)
  • 生产级机器学习系统:从模型部署到系统韧性建设
  • 5G/6G仿真选哪个?TDL与CDL信道模型实战对比与避坑指南
  • K210模型训练踩坑实录:从Mx-yolov3环境配置到Maixpy部署的避坑指南
  • N皇后遗传算法Python实操:从卡死到跑通100解