Python 用chain()组合多个迭代器,可以用chain()
函数将多个迭代器组合为单个迭代器,比如将被groupby()
函数分开的数据重新组合起来。对于简单集合,用这个方法可以一次处理多个集合。
如果需要在一个简单迭代序列中处理多个文件中的数据,可以使用chain()
函数结合contextlib.ExitStack()
方法来实现,具体做法如下:
from contextlib import ExitStack
import csv
def row_iter_csv_tab(*filenames: str) -> Iterator[List[str]]:
with ExitStack() as stack:
files = [
stack.enter_context(cast(TextIO, open(name, 'r')))
for name in filenames
] # type: List[TextIO]
readers = map(
lambda f: csv.reader(f, delimiter='\t'),
files)
yield from chain(*readers)
首先创建了一个包含多个打开的上下文的ExitStack
对象。当with
语句执行完毕后,ExitStack
对象中所有打开的对象都会合理地关闭,所以在ExitStack
对象中创建了多个打开的文件对象。
基于files
变量中的多个文件对象,我们创建了一系列CSV readers对象,保存在readers
变量中。所有文件都是以Tab分隔的,因此便于用一个简单的函数处理所有文件。
也可以用如下方式打开一系列文件:
readers = [csv.reader(f, delimiter='\t') for f in files]
最后,通过chain(*readers)
将多读取器合并成单个迭代器,包含所有文件的行序列数据。
注意,这里不能用
return
返回chain(*readers)
,如果使用return
,函数将退出with
语句,关闭所有文件,所以这里必须用yield
返回某个文件的所有行,同时不退出with
语句。