防止迭代器受到其定义中使用的变量更改的影响

时间:2017-11-02 17:59:14

标签: python iterator immutability

修改/溶液

这是一个更贴切地模仿我的真实问题的示例,以及通过jonrsharpe实现评论的解决方案。谢谢!

import io
import heapq


# THIS DOES NOT WORK AS INTENDED
files = dict(f0=io.StringIO("first line\nsecond line"),
             f1=io.StringIO("FIRST LINE\nSECOND 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 line\nsecond line"),
             f1=io.StringIO("FIRST LINE\nSECOND 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)]?也就是说,我希望结果不会受到在迭代器const定义后对it所做的更改的影响。

>>> const = 1
>>> var = range(2)
>>> it = ((const, i) for i in var)
>>> const = 2
>>> list(it)
[(2, 0), (2, 1)]

我的真实问题是heapq.merge多个文件,而不将所有内容保存在内存中。我想以编程方式生成迭代器,报告文件名以及每个文件的每一行,例如: ("file2.txt", "this is line 1")。目前,我的所有迭代器最终都报告了相同的文件名。

1 个答案:

答案 0 :(得分:0)

您可以将生成器表达式从模块范围移动到函数中,因此从函数范围读取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)]