Ответ 1
Давайте сломаем его.
Простое понимание списка:
[x for x in collection]
Это легко понять, если мы разложим его на части: [A for B in C]
-
A
- это элемент, который будет в результирующем списке -
B
- это каждый элемент коллекцииC
-
C
- это сама коллекция.
Таким образом, можно написать:
[x.lower() for x in words]
Чтобы преобразовать все слова в список в нижний регистр.
Это когда мы усложняем это следующим списком:
[x for y in collection for x in y] # [A for B in C for D in E]
Здесь происходит нечто особенное. Мы хотим, чтобы наш окончательный список включал элементы A
, а элементы A
находились внутри элементов B
, поэтому мы должны рассказать о понимании этого списка.
-
A
- это элемент, который будет в результирующем списке -
B
- это каждый элемент коллекцииC
-
C
- это сама коллекция -
D
- это каждый элемент в коллекцииE
(в этом случае такжеA
) -
E
- это еще одна коллекция (в данном случаеB
)
Эта логика аналогична нормальной для цикла:
for y in collection: # for B in C:
for x in y: # for D in E: (in this case: for A in B)
# receive x # # receive A
Чтобы развернуть это и дать отличный пример + объяснение, представьте, что есть поезд.
Двигатель поезда (фронт) всегда будет там (результат понимания списка)
Тогда есть любое количество вагонов-вагонов, каждый вагон-фургон в форме: for x in y
Понимание списка может выглядеть так:
[z for b in a for c in b for d in c ... for z in y]
Какой будет такой регулярный цикл for:
for b in a:
for c in b:
for d in c:
...
for z in y:
# have z
Другими словами, вместо того, чтобы спускать строку и отступы, в понимании списка вы просто добавляете следующий цикл в конец.
Чтобы вернуться к аналогии поезда:
Engine
- Car
- Car
- Car
... Tail
Что такое хвост? Хвост - особая вещь в понимании списка. Вам это не нужно, но если у вас есть хвост, хвост - это условие, посмотрите на этот пример:
[line for line in file if not line.startswith('#')]
Это даст вам каждую строку в файле, если строка не начиналась с хэштега (#
), другие просто пропущены.
Трюк с использованием "хвоста" поезда состоит в том, что он проверяется на наличие True/False одновременно с вашим окончательным "двигателем" или "результатом" из всех циклов, приведенный выше пример в регулярном for-loop будет выглядеть так:
for line in file:
if not line.startswith('#'):
# have line
обратите внимание: Хотя по моей аналогии с поездом в конце поезда есть только "хвост", состояние или "хвост" может быть после каждого "автомобиля" или цикла...
например:
>>> z = [[1,2,3,4],[5,6,7,8],[9,10,11,12]]
>>> [x for y in z if sum(y)>10 for x in y if x < 10]
[5, 6, 7, 8, 9]
В регулярном для цикла:
>>> for y in z:
if sum(y)>10:
for x in y:
if x < 10:
print x
5
6
7
8
9