Списки в Python
В этой статье мы подробно рассмотрим списки (list) в Python — один из самых гибких и часто используемых типов данных. Списки позволяют хранить коллекции элементов и манипулировать ими различными способами.
Что такое список?
Список в Python — это упорядоченная, изменяемая коллекция элементов, которые могут быть разных типов. Вы можете представить список как контейнер, в котором хранятся различные объекты, расположенные в определенном порядке.
Основные свойства списков:
- Упорядоченность: элементы хранятся в том порядке, в котором они были добавлены
- Изменяемость: можно добавлять, удалять и изменять элементы после создания списка
- Индексируемость: к каждому элементу можно обратиться по его позиции (индексу)
- Допускают дубликаты: один и тот же элемент может встречаться в списке несколько раз
Создание списков
Существует несколько способов создания списков в Python:
С помощью квадратных скобок []
# Пустой список >>> empty_list = [] >>> print(empty_list)
[]# Список чисел >>> numbers = [1, 2, 3, 4, 5] >>> print(numbers)[1, 2, 3, 4, 5]# Список строк >>> fruits = ["яблоко", "банан", "вишня"] >>> print(fruits)['яблоко', 'банан', 'вишня']# Список разных типов данных >>> mixed = [1, "привет", True, 3.14] >>> print(mixed)[1, 'привет', True, 3.14]# Вложенные списки (список списков) >>> matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]] >>> print(matrix)[[1, 2, 3], [4, 5, 6], [7, 8, 9]]
С помощью конструктора list()
# Создание пустого списка >>> empty_list = list() >>> print(empty_list)
[]# Создание списка из строки (каждый символ становится элементом) >>> chars = list("Python") >>> print(chars)['P', 'y', 't', 'h', 'o', 'n']# Создание списка из других итерируемых объектов >>> tuple_to_list = list((1, 2, 3)) >>> print(tuple_to_list)[1, 2, 3]>>> set_to_list = list({1, 2, 3}) >>> print(set_to_list)[1, 2, 3]
С помощью генераторов списков
# Создание списка квадратов чисел от 0 до 9 >>> squares = [x**2 for x in range(10)] >>> print(squares)
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]# Создание списка четных чисел от 0 до 9 >>> even_numbers = [x for x in range(10) if x % 2 == 0] >>> print(even_numbers)[0, 2, 4, 6, 8]# Генератор вложенных списков (матрица 3x3) >>> matrix = [[i + j for j in range(3)] for i in range(0, 9, 3)] >>> print(matrix)[[0, 1, 2], [3, 4, 5], [6, 7, 8]]
Доступ к элементам списка
Индексация
В Python индексация начинается с 0, то есть первый элемент имеет индекс 0, второй — 1, и так далее:
>>> fruits = ["яблоко", "банан", "вишня", "груша", "апельсин"] # Получение элементов по индексу >>> first_fruit = fruits[0] >>> print(f"Первый фрукт: {first_fruit}")
Первый фрукт: яблоко>>> second_fruit = fruits[1] >>> print(f"Второй фрукт: {second_fruit}")Второй фрукт: банан# Отрицательные индексы для доступа с конца списка >>> last_fruit = fruits[-1] >>> print(f"Последний фрукт: {last_fruit}")Последний фрукт: апельсин>>> second_last = fruits[-2] >>> print(f"Предпоследний фрукт: {second_last}")Предпоследний фрукт: груша
Срезы (slices)
Срезы позволяют получить подсписок, указав начальный и конечный индексы:
>>> fruits = ["яблоко", "банан", "вишня", "груша", "апельсин"] # Синтаксис среза: список[начало:конец:шаг] # Начало включается, конец не включается! # Первые три элемента >>> first_three = fruits[0:3] >>> print(f"Первые три фрукта: {first_three}")
Первые три фрукта: ['яблоко', 'банан', 'вишня']# То же самое, но начальный индекс можно опустить, если он 0 >>> first_three = fruits[:3] >>> print(f"Первые три фрукта: {first_three}")Первые три фрукта: ['яблоко', 'банан', 'вишня']# От второго до четвертого >>> middle = fruits[1:4] >>> print(f"Фрукты с индексами 1-3: {middle}")Фрукты с индексами 1-3: ['банан', 'вишня', 'груша']# От третьего до конца >>> to_end = fruits[2:] >>> print(f"Фрукты с третьего до конца: {to_end}")Фрукты с третьего до конца: ['вишня', 'груша', 'апельсин']# Каждый второй элемент >>> every_second = fruits[::2] >>> print(f"Каждый второй фрукт: {every_second}")Каждый второй фрукт: ['яблоко', 'вишня', 'апельсин']# Разворот списка >>> reversed_list = fruits[::-1] >>> print(f"Список в обратном порядке: {reversed_list}")Список в обратном порядке: ['апельсин', 'груша', 'вишня', 'банан', 'яблоко']
Изменение элементов списка
В отличие от строк, списки являются изменяемыми, то есть вы можете изменять, добавлять и удалять элементы:
>>> fruits = ["яблоко", "банан", "вишня"] # Изменение элемента >>> fruits[0] = "киви" >>> print(fruits)
['киви', 'банан', 'вишня']# Изменение нескольких элементов с помощью среза >>> numbers = [1, 2, 3, 4, 5] >>> numbers[1:4] = [20, 30, 40] >>> print(numbers)[1, 20, 30, 40, 5]# Можно даже заменить несколько элементов на другое количество >>> numbers = [1, 2, 3, 4, 5] >>> numbers[1:4] = [20, 30] >>> print(numbers)[1, 20, 30, 5]
Основные методы списков
Python предоставляет множество встроенных методов для работы со списками:
Добавление элементов
>>> fruits = ["яблоко", "банан"] # Добавление элемента в конец списка >>> fruits.append("вишня") >>> print(fruits)
['яблоко', 'банан', 'вишня']# Вставка элемента на определенную позицию >>> fruits.insert(1, "апельсин") >>> print(fruits)['яблоко', 'апельсин', 'банан', 'вишня']# Добавление элементов из другого списка >>> more_fruits = ["груша", "виноград"] >>> fruits.extend(more_fruits) >>> print(fruits)['яблоко', 'апельсин', 'банан', 'вишня', 'груша', 'виноград']# Объединение списков с помощью оператора + >>> combined = fruits + ["ананас", "манго"] >>> print(combined)['яблоко', 'апельсин', 'банан', 'вишня', 'груша', 'виноград', 'ананас', 'манго']
Удаление элементов
>>> fruits = ["яблоко", "банан", "вишня", "апельсин", "банан"] # Удаление элемента по значению (удаляет только первое вхождение) >>> fruits.remove("банан") >>> print(fruits)
['яблоко', 'вишня', 'апельсин', 'банан']# Удаление элемента по индексу и возврат его значения >>> removed = fruits.pop(1) >>> print(f"Удален: {removed}")Удален: вишня>>> print(f"Список после удаления: {fruits}")Список после удаления: ['яблоко', 'апельсин', 'банан']# Если индекс не указан, pop() удаляет и возвращает последний элемент >>> last = fruits.pop() >>> print(f"Последний элемент: {last}")Последний элемент: банан>>> print(fruits)['яблоко', 'апельсин']# Удаление всех элементов из списка >>> fruits.clear() >>> print(f"Пустой список: {fruits}")Пустой список: []# Оператор del для удаления элементов по индексу или срезу >>> numbers = [1, 2, 3, 4, 5] >>> del numbers[0] >>> print(numbers)[2, 3, 4, 5]>>> del numbers[1:3] >>> print(numbers)[2, 5]
Поиск и подсчет элементов
>>> fruits = ["яблоко", "банан", "вишня", "банан", "груша"] # Проверка наличия элемента в списке >>> print("банан" in fruits)
True>>> print("арбуз" in fruits)False# Поиск индекса первого вхождения элемента >>> banana_index = fruits.index("банан") >>> print(f"Индекс первого банана: {banana_index}")Индекс первого банана: 1# Подсчет количества вхождений элемента >>> banana_count = fruits.count("банан") >>> print(f"Количество бананов: {banana_count}")Количество бананов: 2
Сортировка и разворот
# Сортировка списка (изменяет исходный список) >>> numbers = [3, 1, 4, 1, 5, 9, 2] >>> numbers.sort() >>> print(f"Отсортированный список: {numbers}")
Отсортированный список: [1, 1, 2, 3, 4, 5, 9]# Сортировка в обратном порядке >>> numbers.sort(reverse=True) >>> print(f"Обратная сортировка: {numbers}")Обратная сортировка: [9, 5, 4, 3, 2, 1, 1]# Для строк сортировка идет по алфавиту >>> fruits = ["банан", "яблоко", "вишня", "груша"] >>> fruits.sort() >>> print(f"Фрукты по алфавиту: {fruits}")Фрукты по алфавиту: ['банан', 'вишня', 'груша', 'яблоко']# Разворот списка (изменяет исходный список) >>> fruits.reverse() >>> print(f"Фрукты в обратном порядке: {fruits}")Фрукты в обратном порядке: ['яблоко', 'груша', 'вишня', 'банан']# Если не хотите изменять исходный список, используйте sorted() >>> original = [3, 1, 4, 1, 5] >>> sorted_list = sorted(original) >>> print(f"Оригинал: {original}")Оригинал: [3, 1, 4, 1, 5]>>> print(f"Отсортированная копия: {sorted_list}")Отсортированная копия: [1, 1, 3, 4, 5]
Копирование списков
При работе со списками важно понимать, как работает присваивание и копирование:
# Создаем список >>> original = [1, 2, 3] # Присваивание не создает копию — обе переменные указывают на один список >>> reference = original >>> reference.append(4) >>> print(f"Оригинал после изменения ссылки: {original}")
Оригинал после изменения ссылки: [1, 2, 3, 4]# Правильные способы копирования списка: # 1. Метод copy() >>> copy1 = original.copy() # 2. Использование среза [:] >>> copy2 = original[:] # 3. Функция list() >>> copy3 = list(original) # Проверим, что копии не связаны с оригиналом >>> copy1.append(5) >>> print(f"Оригинал: {original}")Оригинал: [1, 2, 3, 4]>>> print(f"Копия 1: {copy1}")Копия 1: [1, 2, 3, 4, 5]# Но осторожно с вложенными списками - это будет "неглубокая" копия >>> nested = [[1, 2], [3, 4]] >>> shallow_copy = nested.copy() >>> shallow_copy[0][0] = 99 >>> print(f"Оригинал вложенного списка: {nested}")Оригинал вложенного списка: [[99, 2], [3, 4]]# Для "глубокой" копии используйте модуль copy >>> import copy >>> deep_copy = copy.deepcopy(nested) >>> deep_copy[0][0] = 100 >>> print(f"Вложенный оригинал: {nested}")Вложенный оригинал: [[99, 2], [3, 4]]>>> print(f"Глубокая копия: {deep_copy}")Глубокая копия: [[100, 2], [3, 4]]
Практический пример использования списка
# Список студентов и их оценок >>> students = ["Анна", "Иван", "Мария", "Петр", "Елена"] >>> grades = [95, 82, 90, 78, 88] # Нахождение студента с наивысшим баллом >>> highest_score = max(grades) >>> top_student_index = grades.index(highest_score) >>> print(f"Лучший студент: {students[top_student_index]} с оценкой {highest_score}")
Лучший студент: Анна с оценкой 95# Расчет средней оценки >>> average_grade = sum(grades) / len(grades) >>> print(f"Средняя оценка: {average_grade:.2f}")Средняя оценка: 86.60
Распространенные ошибки при работе со списками
1. Изменение списка во время итерации
# Неправильно: >>> numbers = [1, 2, 3, 4, 5] >>> try: ... for number in numbers: ... if number % 2 == 0: ... # Опасно! Изменяет список во время итерации ... numbers.remove(number) ... print(numbers) ... except Exception as e: ... print(f"Этот код может вызвать неожиданное поведение")
Этот код может вызвать неожиданное поведение# Правильно: >>> numbers = [1, 2, 3, 4, 5] >>> odd_numbers = [] >>> for num in numbers: ... if num % 2 != 0: ... odd_numbers.append(num) ... numbers = odd_numbers ... print(f"Только нечетные числа: {numbers}")Только нечетные числа: [1, 3, 5]
2. Неглубокое копирование вложенных списков
# Проблема: >>> original = [[1, 2], [3, 4]] >>> shallow = original.copy() >>> shallow[0][0] = 99 >>> print(f"Оригинал изменился: {original}")
Оригинал изменился: [[99, 2], [3, 4]]# Решение: >>> import copy >>> original = [[1, 2], [3, 4]] >>> deep = copy.deepcopy(original) >>> deep[0][0] = 999 >>> print(f"Оригинал: {original}")Оригинал: [[1, 2], [3, 4]]>>> print(f"Глубокая копия: {deep}")Глубокая копия: [[999, 2], [3, 4]]
3. Выход за границы списка
# Ошибка: >>> numbers = [1, 2, 3] >>> try: ... value = numbers[3] # IndexError: list index out of range ... except IndexError as e: ... print(f"Ошибка: {e}")
Ошибка: list index out of range# Безопасный подход: >>> index = 3 >>> if index < len(numbers): ... value = numbers[index] ... else: ... value = None ... print(f"Значение: {value}")Значение: None
Проверка понимания
Какой из следующих способов правильно создаст копию списка, не связанную с оригиналом?