在Python中,f.readlines()和list(f)有什么区别?
在 Python2 教程 和 Python3 教程 中,第 7.2.1 节 的中间有一句话说:
如果你想把一个文件的所有行放到一个列表里,你可以使用
list(f)
或者f.readlines()
。
所以我想问:这两种把文件对象转换成列表的方法有什么区别呢?我对它们的性能和底层的 Python 对象实现都很感兴趣(也许还有 Python2 和 Python3 之间的区别)。
1 个回答
14
从功能上来说,这两种方法没有区别;它们得到的列表是完全一样的。
从实现的角度来看,一种方法是把文件对象当作一个迭代器来使用(不断调用next(f)
,直到出现StopIteration
),而另一种方法则是用专门的方法来读取整个文件。
在Python 2和3中,这两者的具体含义是有区别的,除非你在Python 2中使用io.open()
。Python 2的文件对象使用了一个隐藏的缓冲区来进行文件迭代,如果你把文件对象的迭代和.readline()
或.readlines()
混在一起用,可能会出问题。
而在Python 3中,io
库(负责处理所有文件的输入输出)并不使用这样的隐藏缓冲区,所有的缓冲都是由一个BufferedIOBase()
包装类来处理的。实际上,io.IOBase.readlines()
的实现在底层也是把文件对象当作迭代器来用的,而TextIOWrapper
的迭代则委托给TextIOWrapper.readline()
,所以list(f)
和f.readlines()
实际上是一样的。
从性能上看,即使在Python 2中也没有真正的区别,因为瓶颈在于文件的输入输出;也就是你从磁盘读取数据的速度。在微观层面上,性能可能会受到其他因素的影响,比如操作系统是否已经缓存了数据,以及行的长度有多长。