learnToCode
learnToCode

Reputation: 393

List Comprehension Python Prime numbers

I came across a solution on Stack Overflow to generate prime numbers using list comprehension. But was unable to understand what does the inner for loop do.

I have tried something like

[x for x in range(5,20) for y in range(2,int(x/2)+1) if any(x%y == 0)]

It throws an error: 'bool' object is not iterable

I know that my syntax is wrong but logically for prime numbers we have a for loop followed by a for loop and then a if condition to calculate remainder(x%y). But the answer on Stack Overflow is

[x for x in range(2, 20) if all(x % y != 0 for y in range(2, x))]

I understood the reason why all is used, but I am unable to get how the condition inside all() is working as ideally for should be following if so that range(2,x) is iterated and y gets values which are in turn used for computing(x%y). How can y be used even before it is has been assigned a value.

Upvotes: 2

Views: 2110

Answers (3)

Tom Ron
Tom Ron

Reputation: 6181

The syntax all and any work on iterable objects (list, sets, etc). Therefore you get an error when you apply it on boolean - x%y==0.

You can use any in the following manner -

[x for x in range(5,20) if not any([x % y == 0 for y in range(2, int(x/2)+1)])]

or -

[x for x in range(2, 20) if not any(x % y == 0 for y in range(2, int(x/2)+1))]

As any and all complement each other.

Upvotes: 1

Chau Loi
Chau Loi

Reputation: 1225

That is just the wonderful thing about list comprehension if it can work normally like the for loop, people wont create it because the for loop is more readable and understandable.

You may find out that the result of list comprehension is always a list, meanwhile the result of for loop would always many single values and these single values is a part of iterable

[x +1 for x in range(1,5)]
[2, 3, 4, 5]

for x in range (1,10): print(x+1)
2
3
4
5

You can simply understand that the loop comprehension already have the list of values, then they just simply feed orderly to the condition value by value. Like this:

[1+1 , 2+1 , 3+1 , 4+1]

Your code is wrong because you inherit too much from the ordinary for loop. Your code written in for loop would be like this:

for x in range(5,20):
    for y in range(2,int(x/2)+1):
        if any(x%y == 0):
            print(x)

And the result would obviously:

TypeError: 'bool' object is not iterable

because any requires an iterable such as a generator expression or a **list** as mentioned above by @meowgoesthedog . Coincidentally, list is just all about list comprehension. However, you need comprehend it in order to utilize the list comprehension well. It sometimes happens to me too, in your case, the for y in range(2,int(x/2)+1) works as a normal for loop.

This is the syntax of list comprehension. enter image description here

In side the condition if which is optional predicate. We can create another list comprehension by following the rules with x%y==0 is output expression and a variable y representing members of the input sequence range(2,int(x/2)+1)

Upvotes: 3

Relandom
Relandom

Reputation: 1039

all() and any() works on itterable objects. For example all([True, True, False, True]) returns False. You cant use any(True) (like in your example: any(x%y == 0))

This statement [x for x in range(2, 20) if all(x % y != 0 for y in range(2, x))] can be translated to this code:

res = []
for x in range(2, 20):
    temporary_list = (x%y != 0 for y in range(2,x))
    if all(temporary_list):
        res.append(x)

Ps. I saw in comments that you are not sure how y is declared. In python, there are more great structures than list of comprehension. One of them is generator of comprehension - I believe it is used in this case.

Upvotes: 2

Related Questions