Я думаю, что единственная запутанная часть в выражении [(x, y) for x in range(5) if x % 2 == 0 for y in range(5) if y % 2 == 1]
заключается в том, что там скрытая flatten
операция скрыта.
Давайте сначала рассмотрим упрощенную версию выражения:
def even(x):
return x % 2 == 0
def odd(x):
return not even(x)
c = map(lambda x: map(lambda y: [x, y],
filter(odd, range(5))),
filter(even, range(5)))
print(c)
# i.e. for each even X we have a list of odd Ys:
# [
# [[0, 1], [0, 3]],
# [[2, 1], [2, 3]],
# [[4, 1], [4, 3]]
# ]
Однако нам нужен примерно такой же, но уплощенный список [(0, 1), (0, 3), (2, 1), (2, 3), (4, 1), (4, 3)]
.
Из официальных документов Python мы можем взять пример функции flatten
:
from itertools import chain
flattened = list(chain.from_iterable(c)) # we need list() here to unroll an iterator
print(flattened)
Что в основном эквивалентно следующему выражению понимания списка:
flattened = [x for sublist in c for x in sublist]
print(flattened)
# ... which is basically an equivalent to:
# result = []
# for sublist in c:
# for x in sublist:
# result.append(x)