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..
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.
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.
The only difference between Generator Comprehension and List Comprehension is that the former uses parentheses.
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.
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)]
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With