Python 的迭代器真的太好用了,尤其是处理大数据集,内存再也不爆了.
去年公司接了一个数据分析的活,数据量大概几百万条。我一开始没多想,跟往常一样用列表把所有数据读到内存里。结果程序跑了不到一半,内存直接飙到8个G,电脑卡得鼠标都动不了。旁边同事看我满头大汗,过来扫了一眼代码,说你把列表改成迭代器试试。我半信半疑改了改,内存占用一下降到了200多M,速度快得离谱。
从那以后我就跟迭代器杠上了。Python里搞迭代器其实特别简单,最常用的就是生成器函数。比如你处理一个大文件,以前我习惯用readlines()一次性读完,现在改用readline()配合yield,一行一行往外吐。整个文件不用全进内存,处理完一行就扔掉,内存稳得很。
有次做爬虫,需要从API接口抓取几千万条商品数据。接口是一次只返回100条,但总共要好几百页。我本来想先把所有页的数据都拿下来存到列表里,再慢慢处理。可是估算了一下,光存这些临时数据就要占好几个G内存。后来用了迭代器,每请求一次接口就yield出一批数据,处理完马上释放。跑了一晚上,内存始终没超过500M。
迭代器还有个好处是懒加载,也就是用到的时候才计算。我之前写一个斐波那契数列的演示程序,如果用列表生成,第100万个数字就把内存撑爆了。改成迭代器后,每次只算出当前需要的数,前面的数字根本不占空间。这种处理无限序列的能力,列表是永远做不到的。
很多新手觉得迭代器难懂,其实就是记住了状态。你每次调用它,它都记住上次停在哪。大数据处理时,这个特性特别关键。你不必关心数据从哪里来、有多少条,只需要拿到一个能不断吐出数据的东西,用for循环接住就行。
我自己写了一个日志分析脚本,每天要处理上百G的服务器日志。最开始用列表读取,跑一次要等半小时,中间还经常内存不足挂掉。改成迭代器后,内存占用从6G降到了100M,分析速度反而快了,因为不再花时间在内存分配和垃圾回收上。现在这个脚本每天定时跑,再也没出过问题。
还有那些数据流处理、实时监控的场景,迭代器简直是天然的匹配方案。你不需要把整个历史数据都装进来,只要跟上当前的数据流即可。我最近在做一个股票交易模拟器,用迭代器实时接收行情,每来一条新数据就计算一次指标,完全不用管之前的数据。
所以说迭代器这个东西,会用了是真的香。尤其是当你面对上百万、上千万条数据时,它能帮你把内存占用降低一个数量级,让你用普通笔记本也能处理企业级的数据量。如果你还在一口气把所有数据读到列表里,不妨试试迭代器,你会发现自己的程序突然就变轻巧了。