""" Урок 30. List comprehension. Стек и очередь — весь код примеров одним файлом. Источник: subjects/python-fundamentals/course/lessons/30-list-comprehension-stack-queue/examples.html Файл собран автоматически (tools/build_lesson_examples.py): правьте страницу урока. Запуск: python lesson-30.py """ # ==================================================================== # Пример 1. Базовый list comprehension и его цикл-эквивалент # ==================================================================== numbers = [1, 4, 6, 7, 9] squares_loop = [] for n in numbers: squares_loop.append(n ** 2) squares_lc = [n ** 2 for n in numbers] print(squares_loop) # [1, 16, 36, 49, 81] print(squares_lc) # [1, 16, 36, 49, 81] print(numbers) # [1, 4, 6, 7, 9] — исходный список не тронут # ==================================================================== # Пример 2. Фильтр if — только часть элементов # ==================================================================== even_numbers = [number for number in range(10) if number % 2 == 0] print(even_numbers) # [0, 2, 4, 6, 8] words = ["cat", "elephant", "dog", "bird", "lion", "ant"] long_words_reversed = [word[::-1] for word in words if len(word) > 3] print(long_words_reversed) # ['tnahpele', 'drib', 'noil'] # ==================================================================== # Пример 3. Условное выражение if...else — оно стоит перед for # ==================================================================== numbers = [2, 7, 5, 4, 1, 1, 7, 8] modified = [number if number % 2 == 0 else -1 for number in numbers] print(modified) # [2, -1, -1, 4, -1, -1, -1, 8] try: eval("[n if n % 2 == 0 for n in range(5)]") except SyntaxError as error: print(f"SyntaxError: {error}") # SyntaxError: expected 'else' after 'if' expression (, line 1) # ==================================================================== # Пример 4. Вложенный comprehension: разворот и обработка матрицы # ==================================================================== matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]] flattened = [value for row in matrix for value in row] row_sums = [sum(row) for row in matrix] doubled_flat = [value * 2 for row in matrix for value in row] print(flattened) # [1, 2, 3, 4, 5, 6, 7, 8, 9] print(row_sums) # [6, 15, 24] print(doubled_flat) # [2, 4, 6, 8, 10, 12, 14, 16, 18] # ==================================================================== # Пример 5. List comprehension против map/filter # ==================================================================== nums = [1, 2, 3, 4, 5] lc_result = [x ** 2 for x in nums if x % 2 == 0] mf_result = list(map(lambda x: x ** 2, filter(lambda x: x % 2 == 0, nums))) print(lc_result) # [4, 16] print(mf_result) # [4, 16] print(lc_result == mf_result) # True # ==================================================================== # Пример 6. zip(): параллельный обход, разная длина, разовый итератор # ==================================================================== names = ["Alice", "Bob", "Charlie"] ages = [25, 30, 35] print(list(zip(names, ages))) # [('Alice', 25), ('Bob', 30), ('Charlie', 35)] short = [10, 20, 30] letters = ["x", "y"] print(list(zip(short, letters))) # [(10, 'x'), (20, 'y')] — третий элемент short потерян, ошибки нет zipped = zip(names, ages) print(list(zipped)) # [('Alice', 25), ('Bob', 30), ('Charlie', 35)] print(list(zipped)) # [] — итератор уже исчерпан # ==================================================================== # Пример 7. Стек (LIFO) на списке: append/pop # ==================================================================== stack = [] stack.append(1) stack.append(2) stack.append(3) print(stack) # [1, 2, 3] top = stack.pop() print("Сняли:", top) # Сняли: 3 print("Стек:", stack) # Стек: [1, 2] print("Верхний:", stack[-1]) # Верхний: 2 def check_parentheses(s): balance_stack = [] for char in s: if char == "(": balance_stack.append(char) elif char == ")": if not balance_stack: return False balance_stack.pop() return not balance_stack print(check_parentheses("(())")) # True print(check_parentheses("(()")) # False print(check_parentheses("())(")) # False # ==================================================================== # Пример 8. Очередь (FIFO) на списке — и почему это медленно # ==================================================================== import time queue = [] queue.append(1) queue.append(2) queue.append(3) print(queue) # [1, 2, 3] first = queue.pop(0) print("Обслужили:", first) # Обслужили: 1 print("Очередь:", queue) # Очередь: [2, 3] print("Первый:", queue[0]) # Первый: 2 n = 20000 lst = list(range(n)) start = time.perf_counter() while lst: lst.pop(0) list_time = time.perf_counter() - start print(f"pop(0) для {n} элементов: {list_time:.4f} c") # pop(0) для 20000 элементов: 0.0388 c # ==================================================================== # Пример 9. Очередь на collections.deque: popleft() и реальная разница в скорости # ==================================================================== from collections import deque queue2 = deque(["print", "scan", "send"]) print(queue2.popleft()) # print dq = deque(range(n)) start = time.perf_counter() while dq: dq.popleft() deque_time = time.perf_counter() - start print(f"popleft() для {n} элементов: {deque_time:.4f} c") print(f"deque быстрее в {list_time / deque_time:.1f} раз") # popleft() для 20000 элементов: 0.0017 c # deque быстрее в 23.4 раз # ==================================================================== # Пример 10. Устойчивая сортировка: sorted(key=...) # ==================================================================== words = ["apple", "dog", "bat", "cat", "banana"] print(sorted(words, key=len)) # ['dog', 'bat', 'cat', 'apple', 'banana'] # dog/bat/cat — длина 3, и они остались в исходном порядке друг относительно друга more_words = ["orange", "mango", "apple", "banana", "kiwi", "cherry"] for w in sorted(more_words, key=len): print(f"{len(w)}: {w}") # 4: kiwi # 5: mango # 5: apple # 6: orange # 6: banana # 6: cherry data = [("a", 2), ("b", 1), ("c", 2), ("d", 1)] print(sorted(data, key=lambda pair: pair[1])) # [('b', 1), ('d', 1), ('a', 2), ('c', 2)] # ==================================================================== # Пример 11. Стек, очередь и comprehension вместе: кольцевой буфер событий # ==================================================================== events = ["login", "click", "logout", "click", "error"] recent = deque(maxlen=3) for e in events: recent.append(e) print(list(recent)) # ['login'] # ['login', 'click'] # ['login', 'click', 'logout'] # ['click', 'logout', 'click'] # ['logout', 'click', 'error'] urgent = [e for e in events if e in ("error", "logout")] print(urgent) # ['logout', 'error']