首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >生成器的Python启动

生成器的Python启动
EN

Stack Overflow用户
提问于 2018-09-28 00:36:55
回答 2查看 72关注 0票数 1

我正在尝试一种通用的方法来生成多个范围或列表的所有组合,例如,

[range(0, 2), range(2, 5), range(4, 6), range(2, 3)]

它应该返回一个2x3x2x1 = 12元素列表。

代码语言:javascript
复制
[[0, 2, 4, 2],
 [0, 2, 5, 2],
 [0, 3, 4, 2],
 [0, 3, 5, 2],
 [0, 4, 4, 2],
 [0, 4, 5, 2],
 [1, 2, 4, 2],
 [1, 2, 5, 2],
 [1, 3, 4, 2],
 [1, 3, 5, 2],
 [1, 4, 4, 2],
 [1, 4, 5, 2]]

到目前为止,这里一切都很好。当我硬编码的时候

代码语言:javascript
复制
x = [ ( [a,b] for a in rgs[0] for b in rgs[1] ) ]
x.append( ( a + [b] for a in x[-1] for b in rgs[2]) )
x.append( ( a + [b] for a in x[-1] for b in rgs[3]) )

我得到了好的结果。但是,当我试图将其概括时,请执行

代码语言:javascript
复制
x = [ ( [a,b] for a in rgs[0] for b in rgs[1] ) ]
for i in range(1,len(rgs)-1):
    x.append( ( a + [b] for a in x[-1] for b in rgs[i+1]) )

我获得了一个6元素列表:

代码语言:javascript
复制
[[0, 2, 2, 2],
 [0, 3, 2, 2],
 [0, 4, 2, 2],
 [1, 2, 2, 2],
 [1, 3, 2, 2],
 [1, 4, 2, 2]]

另外,我注意到的是,前两个之后生成的所有范围都使用rgs[-1]中的范围,而不是正确的范围。我很难理解为什么会发生这种情况,因为我认为这两个代码示例是相同的,但后者是任意大量范围的更普遍的形式。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2018-09-28 01:19:48

您的问题与在循环中创建生成器表达式有关。生成器表达式是作为函数实现的,并且和函数一样,它们可以有在包含的命名空间中查找的“空闲”变量。生成器表达式正在从其定义之外访问i,正因为如此,它们最终看到了您期望的不同的i值。

下面是一个可能更容易理解的例子:

代码语言:javascript
复制
def gen()
   print(i)
   yield 10

x = []
for i in range(3):
    x.append(gen())  # add several generators while `i` has several different values

for g in x:
    list(g)   # consume the generators, so they can print `i`

在这里,我没有将i值用于有用的东西,而是编写了一个生成器函数,它只是打印出来的。如果运行这段代码,您将看到所有生成器输出2,因为这是它们最终运行时(在第一个循环结束后)的i值。

您的情况比较微妙,因为您在创建下一个生成器时正在使用前面的生成器,但总体思路是相同的。您期望在rgs[2]上的生成器表达式循环实际上是在rgs[3]上,因为它实际上是用rgs[i+1]查找的,并且在声明生成器表达式的时候和使用它的时候,i增加了。

票数 1
EN

Stack Overflow用户

发布于 2018-09-28 00:40:30

可以使用itertools.product输出元组列表。

输入:

代码语言:javascript
复制
import itertools

a= [range(0, 2), range(2, 5), range(4, 6), range(2, 3)]
list(itertools.product(*a))

输出:

代码语言:javascript
复制
[(0, 2, 4, 2),
 (0, 2, 5, 2),
 (0, 3, 4, 2),
 (0, 3, 5, 2),
 (0, 4, 4, 2),
 (0, 4, 5, 2),
 (1, 2, 4, 2),
 (1, 2, 5, 2),
 (1, 3, 4, 2),
 (1, 3, 5, 2),
 (1, 4, 4, 2),
 (1, 4, 5, 2)]

在运行第一段代码时,我没有得到相同的结果。我不得不改变一下:

代码语言:javascript
复制
x = [ ( [a,b] for a in rgs[0] for b in rgs[1] ) ]
x.append( ( a + [b] for a in x[-1] for b in rgs[2]) )
x =  list( a + [b] for a in x[-1] for b in rgs[3]) 

大多数不知道迭代工具的人都是这样做的:

代码语言:javascript
复制
x=[]
for i0 in rgs[0]:
    for i1 in rgs[1]:
        for i2 in rgs[2]:
            for i3 in rgs[3]:
                x.append([i0,i1,i2,i3])

或者使用一个列表理解(不要这样做,它是非常混乱的外观):

代码语言:javascript
复制
[[i0,i1,i2,i3] for i3 in rgs[3] for i2 in rgs[2] for i1 in rgs[1] for i0 in rgs[0]]
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/52546783

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档