为什么Python嵌套推导式统计CSV数值频率不符合预期?
合并列表推导式后运行报错的原因分析
核心原因
file.readline() 每次调用都会移动文件的读取指针,你写的嵌套推导式会重复调用该方法9次,第二次及之后调用时无法读到有效数据。
具体逻辑说明
可正常运行的代码逻辑
with open("data.txt") as file: l = [int(s) for s in file.readline().strip().split(",")] a1 = [l.count(i) for i in range(9)] print(a1)
这段代码仅调用1次file.readline(),把整行数据全部读取到内存的列表l中,后续循环统计0到8的出现次数时,全程操作内存中的l,不会再读取文件,因此运行正常。
推导式版本报错的逻辑
with open("data.txt") as file: a2 = [[int(s) for s in file.readline().strip().split(",")].count(i) for i in range(9)] print(a2)
外层for i in range(9)会执行9次循环,每次循环都会完整执行内部的读取、转换、统计逻辑:
- 第1次循环(i=0):文件指针在起始位置,
readline()正常返回第一行数据,统计0的个数 - 第2次循环(i=1):再次调用
readline(),此时文件指针已经移动到第一行末尾,没有更多内容可读,返回空字符串 - 空字符串经过
strip()处理后还是空,用,分割后得到[''],尝试将空字符串转换为int时,就抛出了你遇到的ValueError错误。
注:哪怕你删掉前面a1的相关代码,单独运行这段推导式代码也会报错,问题和前半段代码是否读取过文件无关,是推导式本身的重复读文件逻辑导致的。
一行推导式的正确写法(Python3.8+支持海象运算符)
如果确实要写成单条推导式,可以用海象运算符仅读取一次文件内容,后续循环复用读取结果:
with open("data.txt") as file: a2 = [l.count(i) for i in range(9) if (l := [int(s) for s in file.readline().strip().split(",")])] print(a2)
内容的提问来源于stack exchange,提问作者Nils Magnus
相关产品推荐
相关产品推荐

