Если ты пишешь на Python, то наверняка уже сталкивался со списками (list). Это одна из самых часто используемых структур данных. Но часто новички используют их как «коробку для хранения» и не задействуют весь потенциал. В этой статье разберём, что делает списки в Python особенными, какие у них есть скрытые возможности и как писать с ними чистый, эффективный код.
python
mixed_list = [<span>1</span>, <span>"яблоко"</span>, <span>3.14</span>, [<span>1</span>, <span>2</span>, <span>3</span>], <span>lambda</span> x: x * <span>2</span>]<br>
Ключевые свойства:
python
numbers = [<span>0</span>, <span>1</span>, <span>2</span>, <span>3</span>, <span>4</span>, <span>5</span>, <span>6</span>, <span>7</span>, <span>8</span>, <span>9</span>]<br><br><span># Каждый второй элемент</span><br>even_numbers = numbers[::<span>2</span>] <span># [0, 2, 4, 6, 8]</span><br><br><span># Последние три элемента</span><br>last_three = numbers[-<span>3</span>:] <span># [7, 8, 9]</span><br><br><span># Разворот</span><br>reversed_numbers = numbers[::-<span>1</span>] <span># [9, 8, ..., 0]</span><br>
Задача: получить квадраты всех чётных чисел из списка.
Без comprehension:
python
result = []<br><span>for</span> x <span>in</span> numbers:<br> <span>if</span> x % <span>2</span> == <span>0</span>:<br> result.append(x ** <span>2</span>)<br>
С comprehension (более читаемо и быстро):
python
result = [x ** <span>2</span> <span>for</span> x <span>in</span> numbers <span>if</span> x % <span>2</span> == <span>0</span>]<br>
Здесь мы сразу видим логику: «возьми x, если он чётный, и возведи в квадрат». Это делает код декларативным — мы описываем что хотим получить, а не как это сделать пошагово.
Можно вкладывать условия и даже использовать вложенные списки:
python
<span># Создать матрицу 3x3 с нулями</span><br>matrix = [[<span>0</span> <span>for</span> _ <span>in</span> <span>range</span>(<span>3</span>)] <span>for</span> _ <span>in</span> <span>range</span>(<span>3</span>)]<br>
python
a = [<span>1</span>, <span>2</span>, <span>3</span>]<br>b = a <span># Это ссылка!</span><br>b.append(<span>4</span>)<br><span>print</span>(a) <span># [1, 2, 3, 4] — список 'a' тоже изменился!</span><br><br>c = a[:] <span># Это поверхностная копия (slice)</span><br>c.append(<span>5</span>)<br><span>print</span>(a) <span># [1, 2, 3, 4] — 'a' остался прежним</span><br>
Для глубокого копирования сложных списков (со вложенными объектами) используй модуль copy:
python
<span>import</span> copy<br>deep_copy = copy.deepcopy(complex_list)<br>
python
logs = [<br> <span>"GET /index.html 200 OK"</span>,<br> <span>"POST /login 401 Unauthorized"</span>,<br> <span>"GET /api/data 200 OK"</span>,<br> <span>"DELETE /item 500 Error"</span><br>]<br><br><span># Используем list comprehension и строковые методы</span><br>successful_requests = [line <span>for</span> line <span>in</span> logs <span>if</span> <span>"200"</span> <span>in</span> line]<br><br><span>print</span>(successful_requests)<br><span># Вывод: ['GET /index.html 200 OK', 'GET /api/data 200 OK']</span><br>
Этот подход лаконичен, понятен и легко расширяется (например, можно добавить парсинг URL или времени).
Попробуй переписать какой-нибудь свой старый цикл с for в виде list comprehension — ты удивишься, насколько чище станет код.
Что такое список и почему он так популярен?
Список — это упорядоченная, изменяемая коллекция объектов. В одном списке могут лежать числа, строки, другие списки или даже функции.python
mixed_list = [<span>1</span>, <span>"яблоко"</span>, <span>3.14</span>, [<span>1</span>, <span>2</span>, <span>3</span>], <span>lambda</span> x: x * <span>2</span>]<br>
Ключевые свойства:
- Изменяемость (mutable): можно добавлять, удалять и менять элементы на лету.
- Упорядоченность: элементы хранятся в том порядке, в котором ты их добавил.
- Гибкость: не нужно заранее объявлять тип данных или размер списка.
Базовые операции: от простого к сложному
Начнём с того, что знает каждый, но вспомним для порядка:- Доступ по индексу: my_list[0] — первый элемент, my_list[-1] — последний. Отрицательные индексы — это суперудобно.
- Срезы (slicing): my_list[1:5] вернёт элементы со 2-го по 5-й. А my_list[::-1] мгновенно развернёт список задом наперёд.
- Добавление: append() добавляет в конец, insert() — в конкретное место.
- Удаление: pop() удаляет и возвращает элемент, remove() удаляет по значению, del удаляет по индексу или срезу.
python
numbers = [<span>0</span>, <span>1</span>, <span>2</span>, <span>3</span>, <span>4</span>, <span>5</span>, <span>6</span>, <span>7</span>, <span>8</span>, <span>9</span>]<br><br><span># Каждый второй элемент</span><br>even_numbers = numbers[::<span>2</span>] <span># [0, 2, 4, 6, 8]</span><br><br><span># Последние три элемента</span><br>last_three = numbers[-<span>3</span>:] <span># [7, 8, 9]</span><br><br><span># Разворот</span><br>reversed_numbers = numbers[::-<span>1</span>] <span># [9, 8, ..., 0]</span><br>
Продвинутый уровень: списковые включения (List Comprehensions)
Это «визитная карточка» Python. Вместо громоздкого цикла for можно написать всё в одну строку.Задача: получить квадраты всех чётных чисел из списка.
Без comprehension:
python
result = []<br><span>for</span> x <span>in</span> numbers:<br> <span>if</span> x % <span>2</span> == <span>0</span>:<br> result.append(x ** <span>2</span>)<br>
С comprehension (более читаемо и быстро):
python
result = [x ** <span>2</span> <span>for</span> x <span>in</span> numbers <span>if</span> x % <span>2</span> == <span>0</span>]<br>
Здесь мы сразу видим логику: «возьми x, если он чётный, и возведи в квадрат». Это делает код декларативным — мы описываем что хотим получить, а не как это сделать пошагово.
Можно вкладывать условия и даже использовать вложенные списки:
python
<span># Создать матрицу 3x3 с нулями</span><br>matrix = [[<span>0</span> <span>for</span> _ <span>in</span> <span>range</span>(<span>3</span>)] <span>for</span> _ <span>in</span> <span>range</span>(<span>3</span>)]<br>
Производительность и подводные камни
Хотя списки очень удобны, важно помнить о нюансах:- Вставка в начало: list.insert(0, item) работает медленно (O
), потому что приходится сдвигать все остальные элементы. Если тебе нужно часто добавлять в начало или удалять из начала, используй collections.deque. - Проверка вхождения: if x in my_list — это линейный поиск (O
). Если нужно часто проверять наличие элемента, лучше использовать set или dict. - Ссылки, а не копии: когда ты делаешь b = a, ты не создаёшь новый список, а создаёшь новую ссылку на тот же объект. Изменение b изменит и a.
python
a = [<span>1</span>, <span>2</span>, <span>3</span>]<br>b = a <span># Это ссылка!</span><br>b.append(<span>4</span>)<br><span>print</span>(a) <span># [1, 2, 3, 4] — список 'a' тоже изменился!</span><br><br>c = a[:] <span># Это поверхностная копия (slice)</span><br>c.append(<span>5</span>)<br><span>print</span>(a) <span># [1, 2, 3, 4] — 'a' остался прежним</span><br>
Для глубокого копирования сложных списков (со вложенными объектами) используй модуль copy:
python
<span>import</span> copy<br>deep_copy = copy.deepcopy(complex_list)<br>
Практический пример: парсинг логов
Допустим, у тебя есть список строк с логами, и нужно вытащить только успешные запросы (статус 200).python
logs = [<br> <span>"GET /index.html 200 OK"</span>,<br> <span>"POST /login 401 Unauthorized"</span>,<br> <span>"GET /api/data 200 OK"</span>,<br> <span>"DELETE /item 500 Error"</span><br>]<br><br><span># Используем list comprehension и строковые методы</span><br>successful_requests = [line <span>for</span> line <span>in</span> logs <span>if</span> <span>"200"</span> <span>in</span> line]<br><br><span>print</span>(successful_requests)<br><span># Вывод: ['GET /index.html 200 OK', 'GET /api/data 200 OK']</span><br>
Этот подход лаконичен, понятен и легко расширяется (например, можно добавить парсинг URL или времени).
Когда списки — не лучший выбор?
Python богат на структуры данных, и важно знать, когда брать не список:- Нужны уникальные элементы и быстрый поиск: бери set.
- Нужна связь «ключ-значение»: бери dict.
- Нужно хранить неизменяемую последовательность (например, координаты точки): бери tuple.
- Нужна очередь (FIFO) с частыми вставками/удалениями с обоих концов: бери deque из collections.
Заключение
Списки в Python — это фундамент. Они просты для старта, но обладают глубиной, которая раскрывается по мере роста твоего опыта. Умение грамотно использовать срезы, списковые включения и понимание того, как списки работают «под капотом», напрямую влияет на качество твоего кода.Попробуй переписать какой-нибудь свой старый цикл с for в виде list comprehension — ты удивишься, насколько чище станет код.