Сообщить об ошибке.

Выражение-генератор списка list в Python.

Краткий способ создания списков list.

Понимание выражений-генераторов списков обеспечивает краткий способ создания списков.

Обычно внутри приложений создаются новые списки, в которых каждый элемент является результатом некоторых операций, примененных к каждому члену другой последовательности или итерации, или создаются подпоследовательности тех элементов, которые удовлетворяют определенному условию.

Например мы хотим создать список квадратов:

>>> squares = []
>>> for x in range(10):
...     squares.append(x**2)
...
>>> squares
# [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

Обратите внимание, что код выше создает или перезаписывает переменную с именем x, которая все еще существует после завершения цикла. Мы можем вычислить список квадратов без каких-либо побочных эффектов, используя:

squares = list(map(lambda x: x**2, range(10)))

# это эквивалентно:

squares = [x**2 for x in range(10)]

Последняя запись является более краткой и читабельной. "Список - выражение" состоит из скобок, внутри которых, сначала идет нужное нам выражение, за которым следует предложение for ... in, далее выражение может включать ноль или более подвыражений for ... in или предложения if ... else.

Результатом будет новый список, полученный в результате оценки выражения в контексте предложений for ... in и if ... else которые следуют за ним. Например, этот listcomp объединяет элементы двух списков, если они не равны:

>>> [(x, y) for x in [1,2,3] for y in [3,1,4] if x != y]
[(1, 3), (1, 4), (2, 3), (2, 1), (2, 4), (3, 1), (3, 4)]

# это эквивалентно:

>>> combs = []
>>> for x in [1,2,3]:
...     for y in [3,1,4]:
...         if x != y:
...             combs.append((x, y))
...
>>> combs
[(1, 3), (1, 4), (2, 3), (2, 1), (2, 4), (3, 1), (3, 4)]

Обратите внимание, что порядок операторов for ... in and if ... else одинаков в обоих этих фрагментах.

Если нужное нам выражение является кортежем, как в предыдущем примере, оно должно быть заключено в скобки (x, y).

Примеры использования выражений-генераторов списков:

>>> vec = [-4, -2, 0, 2, 4]

# новый список с удвоенными значениями
>>> [x*2 for x in vec]
# [-8, -4, 0, 4, 8]

# фильтр списка для исключения отрицательных чисел
>>> [x for x in vec if x >= 0]
# [0, 2, 4]

# применить функцию ко всем элементам
>>> [abs(x) for x in vec]
# [4, 2, 0, 2, 4]

# вызов метода для каждого элемента
>>> freshfruit = ['  banana', '  loganberry ', 'passion fruit  ']
>>> [weapon.strip() for weapon in freshfruit]
# ['banana', 'loganberry', 'passion fruit']

# создаст список из кортежей типа (число, квадрат)
>>> [(x, x**2) for x in range(6)]
# [(0, 0), (1, 1), (2, 4), (3, 9), (4, 16), (5, 25)]

# кортеж должен быть заключен в скобки,
# иначе возникнет ошибка
>>> [x, x**2 for x in range(6)]
#   File "<stdin>", line 1, in <module>
#     [x, x**2 for x in range(6)]
#                ^
# SyntaxError: invalid syntax

# сгладим список с помощью двух выражений 'for ... in'
>>> vec = [[1,2,3], [4,5,6], [7,8,9]]
>>> [num for elem in vec for num in elem]
# [1, 2, 3, 4, 5, 6, 7, 8, 9]

Так как Python разрешает переносить все, что находится в скобках, то для более глубокого понимания последнее выражение в примере выше можно записать так:

>>> vec = [
... [1,2,3], 
... [4,5,6], 
... [7,8,9]
]

>>> [
... num
... for elem in vec 
... for num in elem
... ]
# [1, 2, 3, 4, 5, 6, 7, 8, 9]

# или вот еще пример 'понятной' записи
>>> import random
>>> n = 10
>>> tree = [
...         ' '*(n-i)+'/'+''.join(random.choice(' # *') 
...         for _ in range(2*i))+'\\' 
...         for i in range(n)
...         ]
>>> print('\n'.join(tree))
#          /\
#         / *\
#        /#  *\
#       /  * ##\
#      /   *  #*\
#     /# **  * * \
#    /#  #*# *  *#\
#   /   **##  *   #\
#  /  * ** *   #*# #\
# /** **#*## **  # #*\

И самое главное все работает, правда здорово! Используйте эту приятную особенность языка Python в своем коде, что-бы он был более понятным другим.

Списки-выражения могут содержать сложные подвыражения и вложенные функции:

>>> from math import pi
>>> [str(round(pi, i)) for i in range(1, 6)]
# ['3.1', '3.14', '3.142', '3.1416', '3.14159']