Can we only use range() in list comprehension


#1

Hello,
My question is that can we only use range() in list comprehension or we can use something else too, like a list or a variable?
E.g:

range= [range(1,21)}
list = [x for x in range if range % 2 == 0 ]

Is the above piece of the code okay, or there is something wrong in it?
Thank you


#2

There are a couple things amiss with the above, the first being the stray curly brace; that would be a square bracket. It would result in a list within a list so would have only one index, [0]. The second is using a reserved word as a variable name, a practice that should rightly be avoided at all turns.

In Python 2, range() returns a list, so no comprehension there. It’s a list after all. In Python 3, range() returns an iterator, not a list, but we can use the list() constructor to yield a list. Again, no comprehension since it is a list. At any length we would not insert this into another list so no added brackets.

test_range = range(1, 21)         => Python 2
test_range = list(range(1, 21))   => Python 3

Once again, a reserved word has been used as a variable name, a big no-no. If the intention is to use the earlier list, then let’s rename it to something more appropriate…

new_list = [x for x in test_range if test_range % 2 == 0 ]

Anything look out of place in there? Can we take a modulo of a list? No, it will raise a TypeError.

>>> n = list(range(1, 21))
>>> n % 2
Traceback (most recent call last):
  File "<pyshell#115>", line 1, in <module>
    n % 2
TypeError: unsupported operand type(s) for %: 'list' and 'int'
>>> 

We should be using the block parameter in the conditional…

new_list = [x for x in test_range if x % 2 == 0 ]

#3

Try this …

side_lengths = [4, 2, 9, 7, 3, 6]
areas = [slen ** 2 for slen in side_lengths]
print(areas)

… and this …

word = "aardvark"
word_sans_a = "".join([ch for ch in word if ch != "a"])
print(word_sans_a)

Experiment, but as @mtf has cautioned, be careful with the syntactic details.