4

我一直在尝试将此生成器函数转换为生成器表达式,但没有成功。生成器表达式是否可以具有相同的输出?

    def gen5(num):
         for i in range(num):             
             yield i *2
             yield i *10
             yield i *i

    g = gen5(4) 
    list(g)
    [0, 0, 0, 2, 10, 1, 4, 20, 4, 6, 30, 9]

我尝试了以下方法,但得到了 (None, None, None) 输出。

    gen_exp2 = (((yield u*2), (yield u*10) ,(yield u*u)) for u in  range(4))

    list(gen_exp2)

    [0,
     0,
     0,
     (None, None, None),
     2,
     10,
     1,
    (None, None, None),
     4,
    20,
     4,
    (None, None, None),
    6,
    30,
    9,
   (None, None, None)]

我也这样做了,但它提供了 4 个嵌套元组而不是上面的列表。

       gen_exp3 = (((i*2), (i*10), (i*i)) for i in range(4))

       list(gen_exp3)

       [(0, 0, 0), (2, 10, 1), (4, 20, 4), (6, 30, 9)]

另外,如何向生成器表达式添加参数?提前谢谢了。

4

2 回答 2

3

你只需要在 gen exp 中有一个双循环:

num = 4
g = (j for i in range(num) for j in (i*2, i*10, i*i))
print(*g)

输出

0 0 0 2 10 1 4 20 4 6 30 9

正如 Moses 所说,yield在 gen exp 中使用并不是一个好主意。


这是一个可爱的变体,使用map

g = (j for i in range(num) for j in map(i.__mul__, (2, 10, i)))

但是,有些人可能不喜欢使用i.__mul__.


您问:“如何向生成器表达式添加参数?”。好吧,你不能。正如 Moses 所示,您可以创建一个lambda,但实际上您最好创建一个适当的生成器函数。Lambda 应该是匿名函数,因此创建 lambda 并将其绑定到名称是一种相当可疑的做法。;)

于 2017-11-19T17:36:58.610 回答
2

您不需要yield在生成器表达式中使用。

请参阅列表推导和生成器表达式中的 yield,了解为什么这很容易被视为错误,尽管事实并非如此。

您可以使用嵌套推导在生成器表达式中实现相同的目的:

gen_exp2 = (x for u in range(4) for x in (u*2, u*10, u*u))

您可以通过将生成器表达式放入函数中来对其进行参数化:

gen_fun = lambda num: (x for u in range(num) for x in (u*2, u*10, u*u)) 

不过,保留原始方法可能会更好,因为yield在函数中使用可能比在生成器表达式中使用嵌套推导更快,而生成器表达式在没有嵌套的情况下已经很慢了。

于 2017-11-19T17:36:46.967 回答