为何Python中any(生成器表达式)运行速度远快于普通for循环?
为什么
any()搭配生成器表达式比普通Python for循环快数倍? 该问题和Stack Overflow上讨论列表推导、函数式工具与for循环性能差异的帖子内容高度相似,但原帖未对该场景下的数倍性能差给出对应解答。
测试现象
测试在包含10^7个随机字符串的数据集上开展,单字符串平均长度为30,两种写法的性能差距在Linux、Windows平台下稳定存在:
any()搭配生成器表达式的版本,Linux环境耗时2.676秒,Windows PowerShell环境耗时4.54秒:
# 0m2.676s # # 注意:逻辑上此处应该用==而非in # 但从耗时角度看,换成==后运行速度还会更快 # (感谢@Booboo 指出这点) # # 对应位置: ------------++ # || if any("xmuijdswly" in w for w in data): print("FOUND IT")
- 普通手写for循环版本,Linux环境耗时13.476秒,Windows PowerShell环境耗时17.71秒:
# 0m13.476s for d in data: if "xmuijdswly" == d: print("FOUND IT") break
Windows平台测试命令及输出如下:
PS ... > Measure-Command { python test_any.py } TotalSeconds : 4.5402383 PS ...> Measure-Command { python test_for.py } TotalSeconds : 17.7107506
附测试数据生成的C语言代码,可复现测试场景:
$ cat main.c #include <stdio.h> #include <stdlib.h> int main(int argc, char **argv) { FILE *fl=fopen("input.txt", "w+t"); for (int i=0;i<10000000;i++) { int length = 5 + rand() % 50; for (int j=0;j<length;j++) fprintf(fl, "%c", rand() % 26 + 'a'); fprintf(fl, "\n"); } fclose(fl); return 0; }
性能差距的根本原因
数倍的性能差距和判断逻辑本身关系极小,核心来自CPython解释器的执行层级差异:
- 普通手写for循环的全流程运行在Python解释器层:每一轮循环的迭代取值、给临时变量
d赋值、执行相等判断、检查是否触发break、调用print,所有步骤都要逐行执行Python字节码,每一步都伴随栈操作、变量名查找、类型校验、分支跳转等固定开销。在千万次级别的循环下,这些单次看起来很小的开销会被累积成非常大的耗时。 any()是CPython直接用C语言实现的内置函数:搭配生成器表达式使用时,整个迭代取值、判断真值、触发短路退出的核心逻辑全部运行在C原生层面,不需要每轮循环都切回Python解释器执行字节码,也不需要在Python层为每个迭代值绑定临时变量,省掉了绝大多数和解释器交互的固定开销。
测试中
any()版本使用的是计算量更大的子串匹配in,速度依然是纯Python for循环的4~5倍,足以证明解释器开销在这个场景里占了绝对大头。如果把any()版本里的判断也换成等值判断==,性能差距还会进一步拉大。
- 这个差异是CPython的固有实现特性,和操作系统无关:只要核心循环逻辑能下沉到C层执行(比如内置函数、标准库实现的迭代工具),性能都会比纯Python手写的for循环高一个量级,循环次数越多,差距越明显。
内容的提问来源于stack exchange,提问作者OrenIshShalom
相关产品推荐
相关产品推荐

