MichaelRSF
MichaelRSF

Reputation: 896

Multiple yields in a generator expression? Python

I've been trying to convert this generator function into a generator expression, but with no success. Is it possible to have the same output with a generator expression?

    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]

I've tried the following, but get this (None, None, None) output.

    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)]

I've also done this, but it gives 4 nested tuples instead of the list above.

       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)]

Also, how can I add a parameter to a generator expression? Many thanks in advance.

Upvotes: 4

Views: 4592

Answers (2)

PM 2Ring
PM 2Ring

Reputation: 55469

You just need a double loop in the gen exp:

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

output

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

As Moses says, using yield in a gen exp is not a good idea.


Here's a cute variation, using map

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

However, some people might not like that use of i.__mul__.


You asked: "How can I add a parameter to a generator expression?". Well, you can't. You could create a lambda, as Moses shows, but really you're better off making a proper generator function. Lambdas are supposed to be anonymous functions, so creating a lambda and binding it to a name is a rather dubious practice. ;)

Upvotes: 3

Moses Koledoye
Moses Koledoye

Reputation: 78556

You don't need to use yield in a generator expression.

See yield in list comprehensions and generator expressions on why this could easily be considered a bug, although it isn't.

You can use a nested comprehension to achieve the same thing in a generator expression:

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

And you can parameterise this by putting the generator expression in a function:

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

Might be better to keep your original approach though, as using yield in a function may be faster than using a nested comprehension within a generator expression which is already pretty slow without nesting.

Upvotes: 2

Related Questions