← Назад к вопросам

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

2.0 Middle🔥 201 комментариев
#Тестирование

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Списковые генераторы в Python

Списковые генераторы (list comprehensions) — это компактный и эффективный способ создания списков. Это один из самых мощных инструментов Python.

1. Базовый синтаксис

# Обычный способ
squares = []
for x in range(10):
    squares.append(x ** 2)

# Списковый генератор
squares = [x ** 2 for x in range(10)]

print(squares)  # [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

Синтаксис

[выражение for переменная in последовательность]

2. Условие в генераторе

# Только чётные числа
evens = [x for x in range(10) if x % 2 == 0]
print(evens)  # [0, 2, 4, 6, 8]

# Только квадраты чисел > 20
big_squares = [x ** 2 for x in range(10) if x ** 2 > 20]
print(big_squares)  # [25, 36, 49, 64, 81]

# Условное выражение (ternary operator)
result = ["even" if x % 2 == 0 else "odd" for x in range(5)]
print(result)  # ['even', 'odd', 'even', 'odd', 'even']

3. Вложенные циклы

# Создать матрицу 3x3
matrix = [[i * 3 + j for j in range(3)] for i in range(3)]
print(matrix)
# [[0, 1, 2],
#  [3, 4, 5],
#  [6, 7, 8]]

# Развернуть матрицу в список
flat = [x for row in matrix for x in row]
print(flat)  # [0, 1, 2, 3, 4, 5, 6, 7, 8]

# Декартово произведение
pairs = [(x, y) for x in [1, 2] for y in [3, 4]]
print(pairs)  # [(1, 3), (1, 4), (2, 3), (2, 4)]

4. Работа со строками

# Преобразовать строку в список букв
letters = [c.upper() for c in "hello"]
print(letters)  # ['H', 'E', 'L', 'L', 'O']

# Разбить слова на буквы
words = "hello world".split()
letters = [letter for word in words for letter in word]
print(letters)  # ['h', 'e', 'l', 'l', 'o', 'w', 'o', 'r', 'l', 'd']

# Фильтровать слова
words = ["hello", "world", "hi", "python"]
long_words = [w for w in words if len(w) > 3]
print(long_words)  # ['hello', 'world', 'python']

5. Set comprehension (генератор множеств)

# Создать множество
unique_squares = {x ** 2 for x in [1, 2, 2, 3, 3, 3]}
print(unique_squares)  # {1, 4, 9}

# Фильтрация
even_squares = {x ** 2 for x in range(10) if x % 2 == 0}
print(even_squares)  # {0, 4, 16, 36, 64}

6. Dictionary comprehension (генератор словарей)

# Создать словарь {число: квадрат}
squares_dict = {x: x ** 2 for x in range(5)}
print(squares_dict)  # {0: 0, 1: 1, 2: 4, 3: 9, 4: 16}

# С условием
even_squares_dict = {x: x ** 2 for x in range(10) if x % 2 == 0}
print(even_squares_dict)  # {0: 0, 2: 4, 4: 16, 6: 36, 8: 64}

# Инвертировать словарь
original = {"a": 1, "b": 2, "c": 3}
inverted = {v: k for k, v in original.items()}
print(inverted)  # {1: 'a', 2: 'b', 3: 'c'}

# Превратить список в словарь
names = ["Alice", "Bob", "Charlie"]
name_lengths = {name: len(name) for name in names}
print(name_lengths)  # {'Alice': 5, 'Bob': 3, 'Charlie': 7}

7. Generator expression (выражение-генератор)

Это как список, но вычисляет значения по мере необходимости (экономит память):

# Список — всё в памяти
squares_list = [x ** 2 for x in range(1000000)]
print(sys.getsizeof(squares_list))  # ~8 MB

# Генератор — лениво вычисляет
squares_gen = (x ** 2 for x in range(1000000))
print(sys.getsizeof(squares_gen))  # ~128 bytes

# Использовать генератор
for square in squares_gen:
    print(square)  # Вычисляется на лету

# Генератор можно использовать только один раз
sum(squares_gen)  # Потребляет генератор
list(squares_gen)  # Пусто — генератор уже исчерпан

8. Сложные примеры

Фильтрация и трансформация данных

students = [
    {"name": "Alice", "grade": 95},
    {"name": "Bob", "grade": 75},
    {"name": "Charlie", "grade": 88},
]

# Получить имена отличников
failed = [s["name"] for s in students if s["grade"] >= 90]
print(failed)  # ['Alice']

# Преобразовать в другой формат
report = [f"{s['name']}: {s['grade']}%" for s in students]
print(report)  # ['Alice: 95%', 'Bob: 75%', 'Charlie: 88%']

Вложенные структуры данных

# Группировка
data = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
result = [x * 2 for row in data for x in row]
print(result)  # [2, 4, 6, 8, 10, 12, 14, 16, 18]

# Фильтрация вложенных данных
matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
even_elements = [x for row in matrix for x in row if x % 2 == 0]
print(even_elements)  # [2, 4, 6, 8]

Обработка файлов

# Прочитать файл и обработать строки
lines = [line.strip().upper() for line in open('file.txt') if line.strip()]

# Или с контекстным менеджером
with open('file.txt') as f:
    lines = [line.strip().upper() for line in f if line.strip()]

print(lines)

9. Производительность

import timeit

# Список
def traditional():
    result = []
    for x in range(1000):
        if x % 2 == 0:
            result.append(x ** 2)
    return result

# Генератор списка
def comprehension():
    return [x ** 2 for x in range(1000) if x % 2 == 0]

# Генератор
def generator():
    return (x ** 2 for x in range(1000) if x % 2 == 0)

print("Traditional:", timeit.timeit(traditional, number=10000))
print("Comprehension:", timeit.timeit(comprehension, number=10000))
print("Generator:", timeit.timeit(generator, number=10000))

# Результат (примерный):
# Traditional: 4.2s
# Comprehension: 2.1s  (в 2x быстрее!)
# Generator: 1.8s

Генератор списков быстрее традиционного цикла!

10. Когда ИЗБЕГАТЬ списковых генераторов

1. Сложные вложенные генераторы

# ❌ Нечитаемо
result = [[y * 2 for y in x if y % 2 == 0] for x in data if x]

# ✅ Лучше
result = []
for row in data:
    if row:
        filtered = [y * 2 for y in row if y % 2 == 0]
        result.append(filtered)

2. Побочные эффекты

# ❌ Генератор не для этого
result = [print(x) for x in range(5)]  # Печатает и возвращает None

# ✅ Используй цикл
for x in range(5):
    print(x)

3. Очень большие последовательности

# ❌ Съедает всю память
big_list = [x for x in range(1_000_000_000)]

# ✅ Используй генератор
big_gen = (x for x in range(1_000_000_000))
for x in big_gen:
    process(x)

Практические применения

# 1. Валидация данных
emails = [e for e in email_list if "@" in e and "." in e]

# 2. Преобразование типов
numbers = [int(x) for x in string_list]

# 3. Извлечение полей из объектов
names = [user.name for user in users if user.active]

# 4. Дублирование элементов
duplicated = [x for x in numbers for _ in range(2)]
# [1, 2, 2, 3, 3, 4, 4] из [1, 2, 3, 4]

# 5. Комбинирование списков
result = [x + y for x in list1 for y in list2]

Выводы

  • Списковые генераторы — компактнее и быстрее чем циклы
  • Генератор-выражения — экономят память для больших последовательностей
  • Dict/Set comprehension — для создания словарей и множеств
  • Избегайте сложных вложенных структур (нечитаемо)
  • Побочные эффекты — используй циклы, не генераторы
  • Производительность — в 2x быстрее чем традиционные циклы
Какие знаешь списковые генераторы? | PrepBro