Как сгенерировать список в python
Перейти к содержимому

Как сгенерировать список в python

  • автор:

Генераторы списков — Python: Декларативное программирование

В повседневной жизни разработчика часто встречается код, работающий с последовательностями. Это связано с тем, что итераторы встроены в Python и тесно интегрированы в стандартную библиотеку.

Итераторы и операции над ними обычно собираются в конвейеры для данных. Лишь в конце каждого конвейера стоит reduce() или другой потребитель элементов, не передающий элементы дальше.

Большинство таких конвейеров состоит из двух видов операций:

  1. Преобразование отдельных элементов. Эту задачу выполняет функция map() . Она преобразует весь поток с помощью другой функции, обрабатывающей отдельные элементы
  2. Изменение состава элементов, то есть фильтрация или размножение. Фильтровать данные умеет filter() . А уже map() в паре с chain() из модуля itertools превращают каждый элемент в несколько, не меняя при этом уровень вложенности

Для примера представим, что мы хотим получить список чисел вида [0, 0, 2, 2, 4, 4. ] — то есть по две копии возрастающих четных чисел. Напишем подходящий конвейер:

# Получаем поток четных чисел def is_even(x): return x % 2 == 0 list(filter(is_even, range(20))) # [0, 2, 4, 6, 8, 10, 12, 14, 16, 18] # Удваиваем каждое def dup(x): return [x, x] list(map(dup, filter(is_even, range(20)))) # [[0, 0], [2, 2], [4, 4], [6, 6], [8, 8], [10, 10], [12, 12], [14, 14], [16, 16], [18, 18]] # Делаем конвейер опять плоским from itertools import chain list(chain(*map(dup, filter(is_even, range(20))))) # [0, 0, 2, 2, 4, 4, 6, 6, 8, 8, 10, 10, 12, 12, 14, 14, 16, 16, 18, 18] # Вариант в виде однострочника list(chain(*map(lambda x: [x, x], filter(lambda x: x % 2 == 0, range(20))))) # [0, 0, 2, 2, 4, 4, 6, 6, 8, 8, 10, 10, 12, 12, 14, 14, 16, 16, 18, 18] 

Как видите, задача решается соединением готовых элементов, а не написанием всего кода вручную в виде цикла for . Уже здесь виден минус нашего конструктора: если готовых функций над элементами или предикатов нет, то их либо приходится заранее объявлять, либо использовать lambda .

Оба варианта неудобны. Когда другой человек читает наш код с отдельными функциями, ему приходится постоянно прыгать по коду туда-сюда. А lambda просто смотрятся громоздко. Но отчаиваться не нужно: у Python есть синтаксис, который может упростить работу с конвейерами.

Генераторы списков

Попробуем решить ту же задачу другим способом:

[x for num in range(20) for x in [num, num] if num % 2 == 0] # [0, 0, 2, 2, 4, 4, 6, 6, 8, 8, 10, 10, 12, 12, 14, 14, 16, 16, 18, 18] 

Это тоже однострочник. Выглядит он не очень удобно, но к такому синтаксису можно привыкнуть. Попробуем отформатировать все выражение:

[x for num in range(20) for x in [num, num] if num % 2 == 0 ] # [0, 0, 2, 2, 4, 4, 6, 6, 8, 8, 10, 10, 12, 12, 14, 14, 16, 16, 18, 18] 

Теперь код стал похож на два вложенных цикла. Похожий код можно написать и на обычных циклах:

res = [] for y in range(20): for x in [y, y]: if y % 2 == 0: res.append(x) res # [0, 0, 2, 2, 4, 4, 6, 6, 8, 8, 10, 10, 12, 12, 14, 14, 16, 16, 18, 18] 

Код выглядит очень похоже, но есть два различия:

  • В первом варианте мы создаем новый список, а во втором — изменяем заранее созданный
  • Первый вариант — это выражение, а второй — набор инструкций. Следовательно, первый вариант можно использовать как часть любых других выражений. При этом нам не пришлось объявлять вспомогательные функции, лямбды тоже не понадобились

Выражения вида [… for … in …] называются генераторами списков. Рассмотрим составляющие нового синтаксиса.

Генератор списков описывается так:

[ВЫРАЖЕНИЕ for ПЕРЕМЕННАЯ in ИСТОЧНИК if УСЛОВИЕ] 

Рассмотрим этот шаблон подробнее:

  • ВЫРАЖЕНИЕ может использовать ПЕРЕМЕННУЮ и вычисляется в элемент будущего списка
  • ПЕРЕМЕННАЯ — имя, с которым поочередно связываются элементы ИСТОЧНИКА
  • ИСТОЧНИК — любой итератор или итерируемый объект
  • УСЛОВИЕ — выражение, которое использует ПЕРЕМЕННУЮ , вычисляемую на каждой итерации

Если условие оказывается ложным, то вычисление выражения для текущей итерации пропускается — в итоговый список новый элемент не добавится. Если условие вместе с ключевым словом if будет пропущено, то это будет эквивалентно условию if True .

В общем случае переменных может быть несколько. Здесь тоже работает распаковка кортежей и списков, в том числе и вложенных.

Вот несколько примеров:

# квадраты чисел [x*x for x in [1, 2, 3]] # [1, 4, 9] # Коды прописных букв из заданной строки [ord(c) for c in "Hello!!" if c.isalpha() and c.islower()] # [101, 108, 108, 111] # Индексы пар, элементы которых равны друг другу [i for i, (x, y) in enumerate([(1, 2), (4, 4), (5, 7), (0, 0)]) if x == y] # [1, 3] # Пример посложнее: отфильтруем во вложенных списках четные элементы, затем оставим списки длиннее трех элементов list_of_lists = [[1, 2, 3, 5], [7, 11, 8, 0], [21, 12, 2, 7, 1], [1, 3]] # Генерируем внутренний список списков и оставляем только нечетные элементы # Отфильтруем список списков и оставим только списки длиннее 3 [ x for x in [[elem for elem in l if elem % 2 == 1] for l in list_of_lists] if len(x) >= 3] # [[1, 3, 5], [21, 7, 1]] 

Когда использовать генераторы списков

Выше мы увидели, что генераторы списков не отменяют все встроенные функции для работы с итераторами. Одно с другим отлично сочетается.

С другой стороны, лучше не смешивать генераторы списков с функциями map() и filter() — это как раз взаимозаменяемые сущности. Еще не стоит смешивать генераторы списков с какими-либо побочными эффектами. Дело в том, что генераторы позволяют писать довольно лаконичный и компактный код. Не нужно заставлять программиста думать, где и что поменяется при создании списка.

Это касается не только кода с функциями map() и filter() , но и вообще любых декларативных конвейеров. Стоит разделять код, написанный в разных парадигмах, на отдельные однотонные участки. Например, ввод-вывод — это один из основных видов побочных эффектов. Он может находиться в начале конвейера или в его конце, но не в середине.

Как проявляется декларативность генераторов списков

Разберем, чем генератор списка отличается от явно императивного двойного цикла. В цикле можно не только строить список, но и производить другие побочные эффекты — например, изменять объекты списка.

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

Можно взглянуть на отличающиеся части и увидеть, что:

  • Генератор списка описывает результат. Он говорит: «Результирующий список — это список чисел в диапазоне от 1 до 20

Открыть доступ

Курсы программирования для новичков и опытных разработчиков. Начните обучение бесплатно

  • 130 курсов, 2000+ часов теории
  • 1000 практических заданий в браузере
  • 360 000 студентов

Наши выпускники работают в компаниях:

Генераторы списков в Python для начинающих

Генератор списков – это простой для чтения, компактный и элегантный способ создания списка из любого существующего итерируемого объекта. По сути, это более простой способ создания нового списка из значений уже имеющегося списка.

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

Сегодня мы разберем несколько способов создания генератора списков и увидим некоторые их вариации, например:

  1. Простой генератор списка
  2. Генераторы списков с одиночными и вложенными условиями if
  3. Генератор списка с одним и несколькими условиями if и else
  4. Генератор списков с вложенными циклами for

Помимо этого, мы также рассмотрим следующие концепции:

  • Цикл for vs. генератор списка
  • Каковы преимущества генератора списка
  • Когда использовать, а когда лучше избегать генератора списков

Что же такое генераторы списков в Python?

Итак, начнем с синтаксиса генератора списка. Генератор списка – это одна строка кода, которую вы пишете в квадратных скобках. Он состоит из трех компонентов:

  • цикл for
  • условие и выражение (condition)
  • результат (output)

list comprehension

Пример простого генератора списка

Приведенный ниже фрагмент кода является примером простейшего генератора списка. Здесь мы просто перебираем lst и сохраняем все его элементы в списке a :

lst = [1,2,3,4,5,6,7,8,9,10] # простой генератор списка a = [x for x in lst] print(a) # Результат: # [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

Этот код полностью эквивалентен следующему:

for x in lst: a.append(x)

Но в первом случае для создания списка а нам даже не нужен метод append . Вместо этого мы используем генератор.

Идем дальше. В приведенном выше генераторе списка можно использовать любое выражение для изменения исходных элементов lst , например:

# добавить любое число к каждому элементу lst и сохранить результат в a a = [x+1 for x in lst] # вычесть любое число из каждого элемента lst и сохранить в a a = [x-1 for x in lst] # умножить каждый элемент lst на любое число и сохранить в a a = [x*2 for x in lst]

Генератор списка с одиночным и вложенным условием if

В генератор списка также можно добавить if-условие, которое может помочь нам отфильтровать данные. Например, в приведенном ниже коде мы сохраняем в список c все значения lst , большие 4 :

lst = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] c = [x for x in lst if x > 4] print(c) # Результат: # [5, 6, 7, 8, 9, 10]

Этот код выполняет то же самое, что и приведенный ниже:

for x in lst: if x > 4: a.append(x)

Мы также можем добавить в наш генератор списка вложенное условие if . Например, в приведенном ниже коде мы сохраняем в список d все элементы lst , значения которых больше 4 и кратны 2 :

d = [x for x in lst if x > 4 if x%2 == 0] # Результат: # [6, 8, 10]

Этот код эквивалентен данному:

for x in lst: if x > 4: if x % 2 == 0: a.append(x)

Генератор списка с одним и несколькими условиями if и else

Хорошо, теперь давайте посмотрим, как мы можем добавить else после if в генератор списка. Напишем простой генератор списка, который будет сохранять в список e все значения lst , большие 4. Если же какое-то значение меньше 4, вместо него будет сохранена строка less than 4 .

lst = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] # с условиями if и else e = [x if x > 4 else 'less than 4' for x in lst] print(e) # Результат: # ['less than 4', 'less than 4', 'less than 4', 'less than 4', 5, 6, 7, 8, 9, 10]

Следующий код выполняет ту же задачу:

for x in lst: if x > 4: d.append(x) else: d.append('less than 4')

А теперь давайте посмотрим, как работают генераторы списков с несколькими if и else .

В приведенном ниже примере мы сохраняем строку Two , если значение кратно 2. А если значение кратно 3, мы сохраняем Three . Во всех остальных случаях мы сохраняем not 2 & 3 .

f = ['Two' if x%2 == 0 else "Three" if x%3 == 0 else 'not 2 & 3' for x in lst] print(f) # Результат: # ['not 2 & 3', 'Two', 'Three', 'Two', 'not 2 & 3', 'Two', 'not 2 & 3', 'Two', 'Three', 'Two']

Как это работает? Чтобы понять это, мы можем разделить всё условие на три части, после каждого else:

‘Two’ if x%2 == 0 else «Three» if x%3 == 0 else ‘not 2 & 3’

Таким образом, если первое условие if истинно, тогда элемент будет принимать значение Two – в противном случае мы вместо сохранения какого-либо значения перейдем ко второму условию if . По такому же принципу работает команда elif . Во втором if-условии в элемент сохранится Three , если утверждение истинно. В противном случае программа проверит следующее условие. Этого условия у нас нет, поэтому элементу будет присвоено значение, идущее сразу после else, — not 2 & 3 .

Мы можем добиться того же результата, написав код следующим образом:

for x in lst: if x%2 == 0: f.append('Two') elif x%3 == 0: f.append('Three') else: f.append('not 2 & 3')

Теперь-то вы видите силу генератора списков? Он выполняет задачу всего в одной строке, в то время как традиционный цикл for состоит из 7.

Генератор списка с вложенным циклом for

Хорошо! Теперь давайте разберем использование вложенного цикла for в генераторе списка.

Чтобы понять, как это работает, давайте рассмотрим приведенный ниже пример. Здесь мы генерируем все возможные комбинации элементов двух списков: [1, 2, 3] и [3, 2, 1] .

lst = [1,2,3] lst_rev = [3,2,1] g = [(x,y) for x in lst for y in lst_rev] print(g) # Результат: # [(1, 3), (1, 2), (1, 1), (2, 3), (2, 2), (2, 1), (3, 3), (3, 2), (3, 1)]

Традиционным способом эта задача решалась бы так:

for x in lst: for y in lst_rev: f.append((x,y))

Хорошо, а теперь, как и обещали, давайте сравним обычный цикл for и генератор списков.

Циклы vs. генератор списков

Выше мы видели, как генератор списков позволяет выполнять задачу всего в одну строчку, в то время как цикл for требует написания нескольких строк.

Генератор списков не только более компактен, но также его эффективность выше. В некоторых случаях он оказывается в два раза быстрее, чем цикл for .

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

Преимущества генераторов списков

Генератор списков — не только простое, компактное и быстрое, но и надежное решение во многих ситуациях. Его можно использовать в самых разных обстоятельствах. Например, для сопоставления и фильтрации в дополнение к генерации базового списка. Вам не нужно каждый раз изобретать велосипед. Это одна из причин, по которой генераторы списков считаются более «питоничными», чем цикл for .

Когда использовать генератор списков (а когда его лучше избегать)

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

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

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

Примечание редакции Pythonist: узнать больше об использовании генераторов списков можно в статье «Когда использовать List Comprehension в Python».

Заключение

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

Мы также узнали, как написать генератор списка с условием или без него, с вложенными if и else и с вложенным циклом for .

Генераторы списков

В языке программирования Python существует специальная синтаксическая конструкция, которая позволяет по определенным правилам создавать заполненные списки. Такие конструкции называются генераторами списков. Их удобство заключается в более короткой записи программного кода, чем если бы создавался список обычным способом.

Например, надо создать список, заполненный натуральными числами до определенного числа. «Классический» способ будет выглядеть примерно так:

>>> a = [] >>> for i in range(1,15): . a.append(i) . >>> a [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14]

На создание списка ушло три строчки кода. Генератор же сделает это за одну:

>>> a = [i for i in range(1,15)] >>> a [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14]

Здесь конструкция [i for i in range(1,15)] является генератором списка. Вся конструкция заключается в квадратные скобки, что как бы говорит, что будет создан список. Внутри квадратных скобок можно выделить три части: 1) что делаем с элементом (в данном случае ничего не делаем, просто добавляем в список), 2) что берем (в данном случае элемент i ), 3) откуда берем (здесь из объекта range). Части отделены друг от друга ключевыми словами for и in .

Рассмотрим такой пример:

>>> a = [2,-2,4,-4,7,5] >>> b = [i**2 for i in a] >>> b [4, 4, 16, 16, 49, 25]

В данном случае в генераторе списка берется каждый элемент из списка a и возводится в квадрат. Таким образом, 1) что делаем — возводим элемент в квадрат, 2) что берем — элемент, 3) откуда берем — из списка a .

>>> a = >>> b = [i*a[i] for i in a] >>> b [10, 40, 90]

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

>>> a = >>> b = [[i,a[i]] for i in a] >>> b [[1, 10], [2, 20], [3, 30]] >>> c = [j for i in b for j in i] >>> c [1, 10, 2, 20, 3, 30]

В этом примере генерируемый список b состоит из вложенных списков. Если бы в генераторе были опущены квадратные скобки в выражении [i,a[i]] , то произошла бы ошибка. Если все же надо получить одноуровневый список из ключей и значений словаря, надо взять каждый вложенный список и из него взять каждый элемент. Это достигается за счет вложенной конструкции for , что демонстрируется в строчке c = [j for i in b for j in i] . «Классический» синтаксис для заполнения списка c выглядел бы так:

>>> c = [] >>> for i in b: . for j in i: . c.append(j) . >>> c [1, 10, 2, 20, 3, 30]

В конец генератора можно добавлять конструкцию if . Например, надо из строки извлечь все цифры:

>>> a = "lsj94ksd231 9" >>> b = [int(i) for i in a if '0'>> b [9, 4, 2, 3, 1, 9]

Или заполнить список числами, кратными 30 или 31:

>>> a = [i for i in range(30,250) . if i%30 == 0 or i%31 == 0] >>> a [30, 31, 60, 62, 90, 93, 120, 124, 150, 155, 180, 186, 210, 217, 240, 248]

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

Генератор списка list в Python

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

Содержание:

  • Понимание генератора списка;
  • Вложенные генераторы списков;
  • Улучшения в Python 3.12 для генераторов списков, словарей и множеств;
  • Примеры создания простых генераторов списков.

В версии Python 3.12 ускорено выполнение генераторов словарей, списков и множеств до двух раз. Смотрите подраздел «Улучшения в Python 3.12 для генераторов. «

Понимание генератора списка.

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

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

>>> 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) .

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

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

Рассмотрим следующий пример матрицы 3×4, реализованной в виде списка из трех списков длиной 4:

>>> matrix = [ . [1, 2, 3, 4], . [5, 6, 7, 8], . [9, 10, 11, 12], . ] 

Следующий генератор списка будет транспонировать строки и столбцы:

>>> [[row[i] for row in matrix] for i in range(4)] # [[1, 5, 9], [2, 6, 10], [3, 7, 11], [4, 8, 12]] 

Вложенный генератор списка оценивается в контексте следующего за ним for . in , поэтому этот пример эквивалентен:

>>> transposed = [] >>> for i in range(4): . transposed.append([row[i] for row in matrix]) . >>> transposed # [[1, 5, 9], [2, 6, 10], [3, 7, 11], [4, 8, 12]] 

Код выше, в свою очередь, совпадает с таким кодом:

>>> transposed = [] >>> for i in range(4): . # the following 3 lines implement the nested listcomp . transposed_row = [] . for row in matrix: . transposed_row.append(row[i]) . transposed.append(transposed_row) . >>> transposed # [[1, 5, 9], [2, 6, 10], [3, 7, 11], [4, 8, 12]] 

В реальном коде нужно отдавать предпочтение встроенным функциям, а сложные выражения использовать, если нет альтернативы. Функция zip() отлично подойдет для случая, который разбирался выше:

>>> list(zip(*matrix)) # [(1, 5, 9), (2, 6, 10), (3, 7, 11), (4, 8, 12)] 

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

>>> matrix = [ . [1, 2, 3, 4], . [5, 6, 7, 8], . [9, 10, 11, 12], . ] >>> [ . [ . row[i] . for row in matrix . ] . for i in range(4) . ] # [[1, 5, 9], [2, 6, 10], [3, 7, 11], [4, 8, 12]] 

Да-да. И все будет работать!

Улучшения в Python 3.12 для генераторов списков, словарей и множеств

В версии Python 3.12 генераторы словарей, списков и множеств теперь встроены в Python, а не создают новый одноразовый функциональный объект для каждого выполнения вызова. Это ускоряет выполнение таких генераторов до двух раз.

Переменные итерации выражений-генераторов остаются изолированными и не перезаписывают переменную с тем же именем во внешней области, а также не становятся видимыми после выражения. Встраивание выражений-генераторов в Python действительно приводит к нескольким видимым изменениям в поведении:

  • В обратных трассировках больше нет отдельного фрейма для выражений-генераторов, а трассировка/профилирование больше не отображает это выражение как вызов функции.
  • Модуль symtable больше не будет создавать дочерние таблицы символов для каждого выражения-генератора. Теперь локальные значения выражения-генератора будут включены в таблицу символов родительской функции.
  • Вызов locals() внутри выражения-генератора теперь включает переменные извне и больше не включает синтетическую переменную .0 для «аргумента» выражения-генератора.
  • Выражение-генератора, выполняющее итерацию непосредственно через locals() (например, [k for k in locals()] ) при запуске в режиме трассировки (например, измерение покрытия кода), может вызвать исключение «RuntimeError: dictionary changed size during iteration«. Это то же самое поведение, которое уже наблюдалось в циклах for k in locals(): . Чтобы избежать ошибки, сначала необходимо создать список ключей для перебора:

>>> keys = list(locals()) >>> [k for k in keys] 

В версии Python 3.12, переменные, используемые в целевой части выражений-генераторов, которые не сохраняются, теперь могут использоваться в выражениях присваивания (:=). Например, в [(b := 1) for a, b.prop in some_iter] теперь разрешено присвоение b . Обратите внимание, что присвоение переменных, хранящихся в целевой части понятий (например, a ), по-прежнему запрещено. (Добавлено Никитой Соболевом.)

Примеры создания простых генераторов списков.

>>> 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 "", line 1, in # [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'] 
  • КРАТКИЙ ОБЗОР МАТЕРИАЛА.
  • Список Python как аргумент по умолчанию
  • Использование списка в качестве стека
  • Использование списка в качестве очереди
  • Генератор списка list
  • Эффективное использование генераторов списков
  • Операция присваивания на месте и списки
  • Поведение списков Python в разных областях видимости
  • Сравнение и идентичность двух списков
  • Как получить несколько последних элементов списка

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *