undo
search menu close

Генераторы коллекций

📅 8 мая 2025 г. 21:58

Иногда возникает необходимость создать новую коллекцию на основе уже существующей. Представьте, у вас есть список чисел, и вам нужно получить новый список, содержащий только квадраты чётных чисел:

numbers = [1, 2, 3, 4, 5]

Один из способов сделать это – перебрать все элементы списка numbers в цикле for и добавить в новый список квадраты тех чисел, которые делятся на 2 без остатка:

squared_numbers = []
for n in numbers:
    if n % 2 == 0:
        squared_numbers.append(n ** 2)
print(squared_numbers)
# Вывод: [4, 16]

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

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

Генератор списка – это мощный инструмент Python, который позволяет создавать новые списки на основе существующих итерируемых объектов (например, списков, кортежей, строк, диапазонов) с применением определенной логики. Общий синтаксис генератора списка выглядит так:

[выражение for элемент in коллекция if условие]

Давайте разберем каждый элемент этой конструкции:

  • выражение – операция, которая применяется к каждому элементу из коллекции. Результат этого выражения добавляется в новый список. Например, для получения квадрата числа выражение выглядит как n ** 2.
  • элемент – временная переменная, которая последовательно принимает значение каждого элемента из коллекции. В нашем примере с числами это будет n.
  • коллекция – итерируемый объект, который можно перебрать в цикле for. Это может быть список (например, numbers), кортеж, строка и даже результат работы функции range().
  • условие (необязательно) – фильтр, который позволяет выбирать только те элементы из коллекции, которые удовлетворяют определенному логическому выражению. Если условие истинно, то элемент обрабатывается и добавляется в новый список. Например, if n % 2 == 0 отбирает только чётные числа.
    Если условие отсутствует, обрабатываются все элементы.

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

squared_numbers = [n ** 2 for n in numbers if n % 2 == 0]
print(squared_numbers)
# Вывод: [4, 16]

Как видите, код стал значительно короче и легче для восприятия. Он сразу показывает, что для каждого числа n из списка numbers мы хотим получить квадрат его числа n ** 2, если n является чётным, то есть if n % 2 == 0.

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

Новый список может быть создан на основе любой из встроенных коллекций.

numbers_tuple = (0, 5, 16, 0, 1, 0, 1)
no_zero_numbers = [n for n in numbers_tuple if n != 0]
print(no_zero_numbers)
# Вывод: [5, 16, 1, 1]

Здесь новый список no_zero_numbers содержит все ненулевые элемента кортежа numbers_tuple.

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

passwords_set = {"qwerty", "ahif782ls", "12345", "IUkhsjdf87"}
good_passwords = [password for password in passwords_set if len(password) >= 8]
print(good_passwords)
# Вывод: ['ahif782ls', 'IUkhsjdf87']

Здесь в новом списке good_passwords содержатся только пароли, длиной больше 8 символов.

Для использования словаря в качестве коллекции в списочном выражении следует вспомнить о методах dict.keys() и dict.values(), которые позволяют получить перебираемые последовательности ключей и значений:

users_ages = {"dragon99": 23, "dragon2010": 16, "Цветок Лотоса": 34}
users = [username for username in users_ages.keys() if username.startswith("dragon")]
print(users)
# Вывод: ["dragon99", "dragon2010"]

Также мы можем одновременно перебирать последовательность пар (ключ, значение), полученную с помощью метода dict.items().Например, если у нас есть словарь с пользователями и их возрастом, то мы можем извлечь имена только совершеннолетних пользователей:

users_ages = {"dragon99": 23, "печенька": 16, "Цветок Лотоса": 34}
adult_users = [user for user, age in users_ages.items() if age >= 18]
print(adult_users)
# Вывод: ['dragon99', 'Цветок Лотоса']

Здесь переменная user принимает все значения ключей, а переменная age – значений. При этом, как в условии, так и в выражении мы можем использовать обе эти переменные.

Кроме того, источником данных для нового списка может служить последовательность, полученная с функции range():

almost_squared_numbers = [x ** 2 - 1 for x in range(5, 10)]
print(almost_squared_numbers)
# Вывод: [24, 35, 48, 63, 80]

Здесь функция range(5, 10) генерирует последовательность чисел от 5 до 9, а затем каждое число возводится в квадрат и уменьшается на единицу.

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

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

Например, выведем на экран список, содержащий все строки таблицы умножения от 1 до 3:

result = [[i * j for j in range(1, 4) ] for i in range(1, 4)]
print(result)
# Вывод: [[1, 2, 3], [2, 4, 6], [3, 6, 9]]

Здесь внешнее списочное выражение создает три списка, каждый из которых содержит результат умножения текущего числа i на числа от 1 до 3.

Генератор множества

По аналогии со списками, можно создавать и множества с помощью генераторов множеств. Для этого используются фигурные скобки {} вместо квадратных []:

numbers = [1, 2, 2, 3, 3]
numbers_set = {n for n in numbers}
print(numbers_set)
# Вывод: {1, 2, 3}

Генератор множества автоматически удаляет повторяющиеся элементы, что является ключевой особенностью множеств. Так в примере выше были удалены повторяющиеся числа 2 и 3.

Генераторы словарей

Для создания словарей также существует специальный синтаксис – генератор словаря. Он, как и множество, использует фигурные скобки {}, но внутри необходимо указывать пару ключ: значение, разделенных двоеточием:

{выражение_с_ключом: выражение_с_значением for ключ, значение in коллекция if условие}

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

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

Например, создадим словарь из списка кортежей c парами (ключ, значение):

students_and_scores = [
    ("Врубель Михаил Александрович", 100),
    ("Шагал Марк Захарович", 98),
    ("Рерих Николай Константинович", 92)
]
students_scores = {student: score for student, score in students_and_scores}
print(students_scores)
# Вывод: {'Врубель Михаил Александрович': 100, 'Шагал Марк Захарович': 98, 'Рерих Николай Константинович': 92}

Такую же последовательность кортежей можно создать из двух коллекций с помощью функции zip():

artists = ["Репин Илья Иванович", "Айвазовский Иван Константинович", "Левитан Исаак Ильич"]
arts = ("Бурлаки на Волге", "Черное море", "Золотая осень")
artists_arts = {artist: art for artist, art in zip(artists, arts)}
print(artists_arts)
# Вывод: {'Репин Илья Иванович': 'Бурлаки на Волге', 'Айвазовский Иван Константинович': 'Черное море', 'Левитан Исаак Ильич': 'Золотая осень'}

В каждом из созданных кортежей, из которых генерируется словарь, первый элемент взят из списка artists, а второй элемент – из кортежа arts. Поэтому словарь создаётся так же как и в первом примере из списка кортежей.

Также словарь может быть сгенерирован на основе другого словаря:

user_grades = {
    'Математика': [4, 5, 3, 5],
    'Русский язык': [5, 4, 4, 5],
    'Информатика': [5, 4, 5, 4]
}
average_grades = {subject: sum(grades) / len(grades) for subject, grades in user_grades.items()}
print(average_grades)
# Вывод: {'Математика': 4.25, 'Русский язык': 4.5, 'Информатика': 4.5}

Здесь в качестве значения нового словаря используется среднее арифметическое списка значений исходного словаря.

Отсутствие генераторов кортежей

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

Например, попробуем создать кортеж арифметических корней списка целых чисел, используя списочное выражение:

numbers = [1, 4, 9, 16, 25]
root_numbers = (n for n in numbers)
print(root_numbers)
# Вывод: <generator object <genexpr> at 0x7f6bc44a8a00>

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

Просто следует запомнить, что кортеж нельзя сгенерировать с помощью списочного выражения. Однако мы можем сначала создать список, а потом преобразовать его в кортеж с помощью функции tuple():

numbers = [1, 4, 9, 16, 25]
root_numbers = tuple([n for n in numbers])
print(root_numbers)
Задания для самопроверки

1. Дан список: brands = ["Apple", "Samsung", "Xiaomi", "LG"]. Напишите программу, которая на его основе создает новый список, содержащий только те слова, длина которых больше или равна 6 символам. Полученный список должен быть выведен на экран.

 
Ответ

2. Дан список: numbers = [1, 2, 2, 3, 4, 4, 5]. Напишите программу, которая на его основе создаёт и выводит на экран множество, содержащее только чётные числа.

 
Ответ

3. Дан словарь prices = {"Роза красная": 180.5, "Хризантема жёлтая": 355.5, "Пион розовый": 325.5}. Напишите программу, которая на его основе создаёт новый словарь, в котором цены будут увеличены на 10%. Полученный словарь должен быть выведен на экран.

 
Ответ

4. Напишите программу, которая, используя списочное выражение, создаёт матрицу 3 x 3, заполненную нулями. Полученная матрица должен быть выведен на экран, причём каждый вложенный список должен выводиться на новой строке.

 
Ответ

5. Напишите программу, которая запрашивает у пользователя число n и выводит на экран список квадратов первых n натуральных чисел.

Пример входных данных Пример выходных данных
4 [1, 4, 9, 16]
6 [1, 4, 9, 16, 25, 36]
8 [1, 4, 9, 16, 25, 36, 49, 64]
 
Ответ
 
arrow_back_ios Назад

 💬 0 комментариев
person
email