编辑/解决方案
这里有一个更接近我实际问题的例子,以及jonrsharpe实现注释的解决方案。谢谢
import io
import heapq
# THIS DOES NOT WORK AS INTENDED
files = dict(f0=io.StringIO("first linensecond line"),
f1=io.StringIO("FIRST LINEnSECOND LINE"))
iterators = ((line.split() + [fname] for line in f)
for fname, f in files.items())
list(heapq.merge(*iterators))
# [['FIRST', 'LINE', 'f0'],
# ['SECOND', 'LINE', 'f0'],
# ['first', 'line', 'f0'],
# ['second', 'line', 'f0']]
# THIS DOES WORK
files = dict(f0=io.StringIO("first linensecond line"),
f1=io.StringIO("FIRST LINEnSECOND LINE"))
iterators = ((lambda x=fname: ((line.split() + [x]) for line in f))(fname)
for fname, f in files.items())
list(heapq.merge(*iterators))
# [['FIRST', 'LINE', 'f1'],
# ['SECOND', 'LINE', 'f1'],
# ['first', 'line', 'f0'],
# ['second', 'line', 'f0']]
原始问题
如何使下面的Python代码生成[(1, 0), (1, 1)]
而不是[(2, 0), (2, 1)]
?也就是说,我希望结果不受迭代器it
定义后对const
所做更改的影响。
>>> const = 1
>>> var = range(2)
>>> it = ((const, i) for i in var)
>>> const = 2
>>> list(it)
[(2, 0), (2, 1)]
我在现实世界中遇到的问题是,在不将所有内容保存在内存中的情况下,对多个文件进行堆合并。我想以编程方式生成迭代器,将文件名与每个文件的每一行一起报告,例如("file2.txt", "this is line 1")
。目前,我所有的迭代器最终都报告了相同的文件名。
您可以将生成器表达式从模块范围移动到函数中,因此const
值将从函数范围中读取,对const
的进一步更改不会影响生成器表达式的评估:
def hide_gen(const):
return ((const, i) for i in [0, 1])
const = 1
it = hide_gen(const)
const = 2
print(list(it))
# [(1, 0), (1, 1)]