在列表理解中创建多个生成器

时间:2013-04-03 19:02:14

标签: python generator list-comprehension

我正在尝试将相同西装(颜色)的卡片组合在一起并在发生器内排名,并将这些发生器存储在列表理解中。

我提出的解决方案除了所有发生器包含完全相同的卡之外。知道为什么吗?

这是代码

deck=range(52)

gens=[(i for i in deck if i%13==v) for v in range(13)]

基于此,我希望例如:

gens[1].next()
1
gens[1].next()
14


gens[10].next()
10
gens[10].next()
23

但我得到了

gens[1].next()
12

gens[1].next()
25

gens[1].next()
38

列表中的所有生成器返回相同的结果..

2 个答案:

答案 0 :(得分:7)

问题是,生成器表达式中的名称v引用了列表推导中的变量v。因此,当您的生成器表达式实际运行的代码时(当您调用next时),它会查看变量v并看到值12,无论{{1}的值是什么是你创建生成器的时候。

一种解决方法:

v

因为我们定义了一个函数,所以名称deck = range(52) def select_kth(v): return (i for i in deck if i % 13 == v) gens = [select_kth(v) for v in range(13)] 可以存在于自己的命名环境中,因此保持不变。

如果您真的想要,可以在一行中完成:

v

答案 1 :(得分:5)

如果将其转换为等效的嵌套循环,则可以更轻松地查看范围界定问题:

gens = []
for v in range(13):
    def gen():
        for i in deck:
            if i%13 == v:
                yield i
    gens.append(gen())

最终你得到的13个生成器都绑定到v,12的相同值。

因此,这里的解决方案与任何其他范围界定问题相同:您需要创建一个包含v的新范围。最简单的方法是创建一个新函数:

gens = [(lambda x: (i for i in deck if i%13==x)(v) for v in range(13)]