Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

creating multiple generators inside a list comprehension

I am trying to group cards of the same suit (color) and rank inside generators and store those generators inside a list comprehension.

The solution I came up with does that except for the fact that all the generators contain exactly the same cards. Any idea why?

Here is the code

deck=range(52)

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

Based on this I would expect for example:

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


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

But instead I get

gens[1].next()
12

gens[1].next()
25

gens[1].next()
38

And all the generators in the list return the same results..

like image 918
jule64 Avatar asked Apr 03 '13 19:04

jule64


People also ask

Is list comprehension faster than generator?

List comprehensions return the entire list, and the generator expression returns only the generator object. The values will be the same as those in the list, but they will be accessed one at a time by using the next() function. This is what makes list comprehensions faster than generator expressions.

Are list comprehensions memory efficient than generator comprehensions?

So what's the difference between Generator Expressions and List Comprehensions? The generator yields one item at a time and generates item only when in demand. Whereas, in a list comprehension, Python reserves memory for the whole list. Thus we can say that the generator expressions are memory efficient than the lists.

What is the difference between a list comprehension dictionary comprehension and a generator?

The only difference between Generator Comprehension and List Comprehension is that the former uses parentheses.

How do I make a list generator in Python?

To create a generator from a list using the generator function , we will define a generator function that takes a list as input. Inside the function, we will use a for loop in which the yield statement will be used to give the squares of the elements of the existing list as output.


1 Answers

The problem is that the name v in your generator expression refers to that variable v in the list comprehension. So, when the code your generator expression actually runs (when you call next), it looks at the variable v and sees the value 12, no matter what the value of v was when you created the generator.

One workaround:

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

Because we defined a function, the name v gets to live in its own naming environment and so stays around unmodified.

If you really wanted, you could do this in one line:

 gens = [(lambda v: (i for i in deck if i % 13 == v))(v) for v in range(13)]
like image 168
Danica Avatar answered Sep 29 '22 09:09

Danica