Yeah it is Python. Anyway I think you may be right. Thanks for the explanation. The strange thing is that Python does allow you to make lists via [x for y in z], so I don't know why this alternate syntax is being used.
In addition to the other responses I think it's good to consider the statement in detail. The statement can be deconstructed into three separate parts:
Code:
i for
i, prime in enumerate(is_prime)
if prime
The first part
i for creates a list of elements
i. The second part
i, prime in enumerate(is_prime) is a pattern match against a generator. The third part
if prime is a conditional which makes sure that the values
i are added to the list only if their corresponding values
prime are True.
In this context, is_prime is a list of True/False values, corresponding to whether or not the numbers 0, 1, 2, ... are or aren't primes. So:
Code:
i, prime in enumerate(is_prime)
is a generator which yields the indices i and corresponding boolean (whether or not the index is a prime)
prime from the list
is_prime. So the enumerate() yields (
i = index,
prime = True/False) pairings depending on whether the number
i is or isn't a prime number. This will look like this if unrolled:
Code:
i, prime = 0, False # Binds i = 0, prime = False
i, prime = 1, False # i = 1, prime = False
i, prime = 2, True # i = 2, prime = True
...
The right hand side of this statement corresponds to each yielded element from the enumerate function (with different values for
i and
prime).
So, the syntax
Code:
[i for i, prime in enumerate(is_prime) if prime]
taken together creates a list of indices
i of the list is_prime for which the elements are True. For example, from the list is_prime = [False (index 0), False (index 1), True (index 2), True (index 3), ...] the indices [2, 3, ...] are selected and all others are discarded.
As for the statement
Code:
[i for x, prime in enumerate(is_prime) if prime]
what happens is that the second statement unrolls like
Code:
x, prime = 0, False # x = 0, prime = False
x, prime = 1, False # x = 1, prime = False
x, prime = 2, True # x = 2, prime = True
...
This means that the third statements returns True for the same indices as above. However! Note that the three statement are not necessarily dependent on each other! Both of these are correct syntaxes:
Code:
[0 for i in [0, 1, 2, 3]] # This creates the list [0, 0, 0, 0], i is not used.
[i for i in [0, 1, 2, 3] if False] # This creates the empty list [] since the conditional is always False
So what happens in your last case? Basically, the last value that
i was set to is used. This corresponds to:
Code:
i = limit - 1 # ie. 5 if limit = 6
[i for x in [0, 1, 2, 3]] # Creates [5, 5, 5, 5]
I like how these list comprehensions are implemented in Python, although they can be confusing. Especially if you want to use an if/else condition, in which case the conditional comes
before the generator, ugh.
Code:
["even" if i % 2 == 0 else "odd" for i in [0, 1, 2, 3]] # Creates the list ["even", "odd", "even", "odd"]