Whenever you see this pattern to create a list of items:
(values) = [] for (value) in (collection): (values).append((expression))
You can replace it with a list comprehension, which takes the form of:
(values) = [ (expression) for (value) in (collection)]
This:
t = []
for i in range(10):
t.append(i * i)
Can be replaced with:
t = [(i * i) for i in range(10)]
Notice how the variable used to iterate over the collection is made available for calculating the expression which will be added to our resulting list.
squares = [x * x for x in [0, -1, -2, 3, 4]]
print(squares)
# outputs:
[0, 1, 4, 9, 16]
We can of course, add an if expression to the list comprehension, to filter the collection:
even = [x for x in range(10) if x % 2 == 0]
odd = [x for x in range(10) if x % 2 != 0]
print(even)
print(odd)
# outputs:
[0, 2, 4, 6, 8]
[1, 3, 5, 7, 9]
We can also enumerate our collection to make use of the index in our if condition, and/or expression:
even = [x * i for i, x in enumerate(range(10)) if (i > 4) and (x % 2 == 0)]
odd = [x * i for i, x in enumerate(range(10)) if (i > 4) and (x % 2 != 0)]
print(even)
print(odd)
# outputs:
[36, 64]
[25, 49, 81]
Finally, here is an example where I ignore the value and generate a random number three times:
from random import randint
def roll_die():
return [randint(1, 6) for i in range(3)]
# generate footballer attributes
strength = sum(roll_die())
stamina = sum(roll_die())
morale = sum(roll_die())
print(f'str: {strength}')
print(f'sta: {stamina}')
print(f'mor: {morale}')
# outputs:
str: 8
sta: 15
mor: 13