ТЕОРИЯ И ПРАКТИКА
-
Ввод и вывод данных
- Задачи
-
Условия
- Задачи
-
Цикл for
- Задачи
-
Строки
- Задачи
-
Цикл while
- Задачи
-
Списки
- Задачи
-
Двумерные массивы
- Задачи
-
Словари
- Задачи
-
Множества
- Задачи
-
Функции и рекурсия
- Задачи
Занятие 6. Списки и методы списков в питоне
Введение в списки
Списки в Python: определение и типы данных
Списки (list) — это один из самых универсальных и часто используемых встроенных типов данных в Python. По своей сути, список — это упорядоченная и изменяемая коллекция объектов. В одном списке могут храниться элементы совершенно разных типов.
# Чтобы узнать тип переменной, используется функция type()
my_list = [1, 2, 3]
print(type(my_list))
Основные свойства списков
- Упорядоченность (Ordered): Элементы в списке хранятся в определённом порядке. У каждого элемента есть свой индекс (порядковый номер), и этот порядок не изменится, если вы его не измените сами.
- Изменяемость (Mutable): Вы можете изменять список после его создания: добавлять, удалять или изменять его элементы. Это ключевое отличие от кортежей (tuple).
Примеры списков с разными типами данных
Списки в Python чрезвычайно гибкие и могут содержать любые типы данных, даже вперемешку.
# Список целых чисел
numbers = [1, 5, -10, 23]
# Список строк
strings = ["hello", "world", "python"]
# Смешанный список: числа, строки, логические значения и даже None
mixed_list = [10, "apple", True, 3.14, None]
print(numbers)
print(strings)
print(mixed_list)
Создание списков в Python
Создание пустого списка
Есть два основных способа создать пустой список, который позже можно будет наполнить данными.
# Способ 1: с помощью квадратных скобок (наиболее распространённый)
empty_list_1 = []
# Способ 2: с помощью конструктора list()
empty_list_2 = list()
print(f"Пустой список 1: {empty_list_1}")
print(f"Пустой список 2: {empty_list_2}")
Список с элементами одного типа
Чаще всего списки используются для хранения однородных данных.
# Список целых чисел
integer_list = [10, 20, 30, 40, 50]
# Список строк
string_list = ["Москва", "Санкт-Петербург", "Казань"]
print(integer_list)
print(string_list)
Смешанные и вложенные списки
Списки могут содержать другие списки. Такие структуры называются вложенными или двумерными списками и часто используются для представления матриц или таблиц.
# Смешанный список
mixed_data = ["Алексей", 35, "Программист", 185.5, True]
# Вложенный список (матрица 2x3)
matrix = [
[1, 2, 3],
[4, 5, 6]
]
print(f"Данные о сотруднике: {mixed_data}")
print(f"Матрица: {matrix}")
# Доступ к элементу вложенного списка: matrix[строка][столбец]
print(f"Элемент в первой строке, втором столбце: {matrix[0][1]}") # Выведет 2
Обращение к элементам списка
Индексация с начала (положительные индексы)
Индексация в Python начинается с 0. Первый элемент имеет индекс 0, второй — 1, и так далее.
fruits = ["apple", "banana", "cherry", "orange"]
# Получаем первый элемент
first_fruit = fruits[0]
print(f"Первый фрукт: {first_fruit}") # 'apple'
# Получаем третий элемент
third_fruit = fruits[2]
print(f"Третий фрукт: {third_fruit}") # 'cherry'
Индексация с конца (отрицательные индексы)
Отрицательная индексация позволяет обращаться к элементам с конца списка. -1 — это последний элемент, -2 — предпоследний и т.д.
fruits = ["apple", "banana", "cherry", "orange"]
# Получаем последний элемент
last_fruit = fruits[-1]
print(f"Последний фрукт: {last_fruit}") # 'orange'
# Получаем предпоследний элемент
second_to_last_fruit = fruits[-2]
print(f"Предпоследний фрукт: {second_to_last_fruit}") # 'cherry'
Срезы (Slices)
Срезы — это мощный инструмент для получения части списка. Они создают новый список, не изменяя исходный.
Основной синтаксис: list[start:stop:step]
start: индекс, с которого начинается срез (включительно). Если опущен, срез начинается с 0.stop: индекс, на котором заканчивается срез (не включительно!). Если опущен, срез идёт до конца списка.step: шаг, с которым извлекаются элементы. Если опущен, шаг равен 1.
numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
# Срез со 2-го по 5-й элемент (индексы с 1 по 4)
subset = numbers[1:5]
print(f"Срез с 1 по 4 индекс: {subset}") # [1, 2, 3, 4]
# Срез от начала до 4-го элемента (индекс 3)
first_part = numbers[:4]
print(f"Срез от начала до индекса 3: {first_part}") # [0, 1, 2, 3]
# Срез с 5-го элемента (индекс 4) до конца
last_part = numbers[4:]
print(f"Срез от индекса 4 до конца: {last_part}") # [4, 5, 6, 7, 8, 9]
# Получение каждого второго элемента
every_second = numbers[::2]
print(f"Каждый второй элемент: {every_second}") # [0, 2, 4, 6, 8]
# Переворот списка с помощью среза (шаг -1)
reversed_list = numbers[::-1]
print(f"Перевернутый список: {reversed_list}") # [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
Изменение элементов списка
Присваивание значения по индексу
Так как списки изменяемы, вы можете легко заменить один или несколько элементов.
colors = ["red", "green", "blue"]
print(f"Исходный список: {colors}")
# Изменяем второй элемент (индекс 1)
colors[1] = "yellow"
print(f"После изменения одного элемента: {colors}")
# Можно изменять и целый срез
colors[0:2] = ["orange", "purple"]
print(f"После изменения среза: {colors}")
Добавление элементов в список
Метод append()
Добавляет один элемент в самый конец списка.
numbers = [1, 2, 3]
print(f"До append: {numbers}")
numbers.append(4)
print(f"После append(4): {numbers}")
Метод insert()
Вставляет элемент на указанную позицию (индекс).
letters = ['a', 'c', 'd']
print(f"До insert: {letters}")
# Вставляем 'b' на позицию с индексом 1
letters.insert(1, 'b')
print(f"После insert(1, 'b'): {letters}")
Метод extend()
Расширяет список, добавляя в конец все элементы из другой последовательности (например, другого списка).
list1 = [1, 2, 3]
list2 = [4, 5, 6]
print(f"До extend: list1 = {list1}")
list1.extend(list2)
print(f"После extend(list2): list1 = {list1}")
# Сравните с append:
list3 = [1, 2, 3]
list3.append(list2) # append добавит list2 как один вложенный элемент
print(f"Результат с append: {list3}") # [1, 2, 3, [4, 5, 6]]
Удаление элементов из списка
Метод remove()
Удаляет первое найденное вхождение указанного значения. Если значение не найдено, вызывает ошибку ValueError.
pets = ["cat", "dog", "hamster", "dog"]
print(f"До remove: {pets}")
pets.remove("dog") # Удалит первое вхождение "dog"
print(f"После remove('dog'): {pets}")
Метод pop()
Удаляет элемент по указанному индексу и возвращает его. Если индекс не указан, удаляет и возвращает последний элемент.
items = ["book", "pen", "laptop", "mouse"]
print(f"До pop: {items}")
# Удаляем элемент с индексом 1 и сохраняем его
removed_item = items.pop(1)
print(f"Удаленный элемент: {removed_item}")
print(f"После pop(1): {items}")
# Удаляем последний элемент
last_item = items.pop()
print(f"Удаленный последний элемент: {last_item}")
print(f"После pop(): {items}")
Метод clear()
Удаляет все элементы из списка, делая его пустым.
data = [1, 2, 3, 4, 5]
print(f"До clear: {data}")
data.clear()
print(f"После clear: {data}")
Поиск элементов в списке
Метод index()
Возвращает индекс первого вхождения указанного значения. Если значение не найдено, вызывает ошибку ValueError.
numbers = [10, 20, 30, 40, 20, 50]
# Находим индекс первого вхождения числа 30
idx = numbers.index(30)
print(f"Индекс числа 30: {idx}") # 2
# Можно указать начальный индекс для поиска
idx_after_3 = numbers.index(20, 3) # Искать 20, начиная с индекса 3
print(f"Индекс числа 20 после 3-й позиции: {idx_after_3}") # 4
Метод count()
Подсчитывает, сколько раз указанное значение встречается в списке.
grades = ['A', 'B', 'A', 'C', 'A', 'B']
# Считаем количество оценок 'A'
count_a = grades.count('A')
print(f"Количество оценок 'A': {count_a}") # 3
Сортировка списков
Метод sort()
Сортирует список на месте, то есть изменяет исходный список. Ничего не возвращает.
numbers = [3, 1, 4, 1, 5, 9, 2, 6]
print(f"Исходный список: {numbers}")
numbers.sort()
print(f"Отсортированный список: {numbers}")
Функция sorted()
Возвращает новый отсортированный список, оставляя исходный без изменений.
numbers = [3, 1, 4, 1, 5, 9, 2, 6]
print(f"Исходный список: {numbers}")
sorted_numbers = sorted(numbers)
print(f"Новый отсортированный список: {sorted_numbers}")
print(f"Исходный список остался неизменным: {numbers}")
Сортировка в обратном порядке
Оба метода, sort() и sorted(), принимают необязательный аргумент reverse=True.
numbers = [3, 1, 4, 1, 5, 9, 2, 6]
# Сортировка на месте в обратном порядке
numbers.sort(reverse=True)
print(f"Сортировка sort(reverse=True): {numbers}")
# Создание нового списка, отсортированного в обратном порядке
new_sorted_desc = sorted([10, 50, 20], reverse=True)
print(f"Сортировка sorted(reverse=True): {new_sorted_desc}")
Обращение элементов списка
Метод reverse()
Переворачивает порядок элементов в списке на месте.
letters = ['a', 'b', 'c', 'd']
print(f"До reverse: {letters}")
letters.reverse()
print(f"После reverse: {letters}")
Функция reversed()
Возвращает итератор, который проходит по списку в обратном порядке. Исходный список не меняется. Чтобы получить список, результат нужно обернуть в list().
letters = ['a', 'b', 'c', 'd']
print(f"Исходный список: {letters}")
reversed_iterator = reversed(letters)
reversed_list = list(reversed_iterator)
print(f"Новый перевернутый список: {reversed_list}")
print(f"Исходный список не изменился: {letters}")
# Как вы помните, это можно сделать и срезом
reversed_by_slice = letters[::-1]
print(f"Перевернутый список через срез: {reversed_by_slice}")
Копирование списков
Поверхностное копирование через срезы
Присваивание new_list = old_list не создает копию, а лишь новую ссылку на тот же объект. Чтобы создать независимую копию, можно использовать срез [:].
original_list = [1, 2, 3]
# Неправильное копирование (просто ссылка)
ref_list = original_list
ref_list[0] = 99
print(f"Изменили ref_list, а original_list тоже изменился: {original_list}") # [99, 2, 3]
# Правильное копирование через срез
original_list = [1, 2, 3] # Вернем исходное значение
copied_list = original_list[:]
copied_list[0] = 55
print(f"Изменили copied_list: {copied_list}") # [55, 2, 3]
print(f"original_list при этом не изменился: {original_list}") # [1, 2, 3]
Метод copy()
Метод copy() делает то же самое, что и срез [:] — создает поверхностную копию списка.
original_list = [10, 20, 30]
# Копирование с помощью метода copy()
copied_list = original_list.copy()
copied_list[0] = 111
print(f"Изменили копию: {copied_list}")
print(f"Оригинал не изменился: {original_list}")
Таблица основных методов списков
Методы массивов в питоне
| Метод | Описание | Пример кода | Что возвращает? |
|---|---|---|---|
append(x) |
Добавляет элемент x в самый конец списка. |
a = [1, 2] a.append(3) print(a) # -> [1, 2, 3] |
None |
extend(iterable) |
Расширяет список, добавляя в конец все элементы из переданного итерируемого объекта (например, другого списка). | a = [1, 2] b = [3, 4] a.extend(b) print(a) # -> [1, 2, 3, 4] |
None |
insert(i, x) |
Вставляет элемент x на позицию с индексом i. |
a = [1, 3] a.insert(1, 2) print(a) # -> [1, 2, 3] |
None |
remove(x) |
Удаляет первое найденное в списке значение x. Если такого элемента нет, вызывает ошибку ValueError. |
a = [1, 2, 3, 2] a.remove(2) print(a) # -> [1, 3, 2] |
None |
pop([i]) |
Удаляет элемент на позиции i и возвращает его. Если индекс i не указан, удаляет и возвращает последний элемент. |
a = [1, 2, 3] x = a.pop(1) print(a, x) # -> [1, 3] 2 |
Удаленный элемент |
clear() |
Очищает список, удаляя из него все элементы. | a = [1, 2, 3] a.clear() print(a) # -> [] |
None |
index(x[, start[, end]]) |
Возвращает индекс первого вхождения элемента x. Можно ограничить поиск срезом [start:end]. |
a = ['a', 'b', 'c'] i = a.index('b') print(i) # -> 1 |
Индекс элемента (число) |
count(x) |
Возвращает количество вхождений элемента x в списке. |
a = [1, 2, 3, 2] c = a.count(2) print(c) # -> 2 |
Количество вхождений (число) |
sort(key=None, reverse=False) |
Сортирует элементы списка на месте (in-place). key - функция для вычисления ключа, reverse=True для сортировки по убыванию. |
a = [3, 1, 2] a.sort() print(a) # -> [1, 2, 3] |
None |
reverse() |
Разворачивает порядок элементов в списке на месте (in-place). | a = [1, 2, 3] a.reverse() print(a) # -> [3, 2, 1] |
None |
copy() |
Создает и возвращает поверхностную копию списка. Эквивалентно срезу [:]. |
a = [1, 2] b = a.copy() b.append(3) print(a, b) # -> [1, 2] [1, 2, 3] |
Новый список (копия) |
Важный момент: многие методы, такие как sort(), reverse(), append() и другие, изменяют список "на месте" (in-place) и возвращают None. Это частая причина ошибок у начинающих, которые пытаются присвоить результат такой операции другой переменной.
Особенности работы со списками разных типов
Списки строк и работа с join
Метод строк .join() позволяет объединить элементы списка строк в одну строку с указанным разделителем.
words = ["Python", "is", "awesome"]
# Объединяем слова через пробел
sentence = " ".join(words)
print(sentence) # "Python is awesome"
# Объединяем через запятую
csv_string = ",".join(words)
print(csv_string) # "Python,is,awesome"
Списки чисел и операции над ними
Со списками чисел удобно работать с помощью встроенных функций и генераторов.
numbers = [1, 2, 3, 4, 5]
# Получение нового списка с квадратами чисел (см. раздел про генераторы)
squares = [x * x for x in numbers]
print(f"Квадраты чисел: {squares}")
Списки логических значений и функции all(), any()
all(list)возвращаетTrue, если все элементы списка истинны.any(list)возвращаетTrue, если хотя бы один элемент списка истинен.
bool_list_1 = [True, True, True]
bool_list_2 = [True, False, True]
bool_list_3 = [False, False, False]
print(f"all(bool_list_1): {all(bool_list_1)}") # True
print(f"all(bool_list_2): {all(bool_list_2)}") # False
print(f"any(bool_list_2): {any(bool_list_2)}") # True
print(f"any(bool_list_3): {any(bool_list_3)}") # False
Двумерные списки и их обход
Для обхода двумерных списков (матриц) используются вложенные циклы.
matrix = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9]
]
# Проход по матрице и печать каждого элемента
for row in matrix: # Сначала итерируемся по строкам
for element in row: # Затем по элементам в каждой строке
print(element, end=" ")
print() # Переход на новую строку после каждой строки матрицы
Итерация по спискам
Простой перебор элементов
Самый частый способ — цикл for.
colors = ["red", "green", "blue"]
for color in colors:
print(f"Текущий цвет: {color}")
Перебор с использованием enumerate()
Когда нужен не только элемент, но и его индекс, используйте enumerate().
colors = ["red", "green", "blue"]
for index, color in enumerate(colors):
print(f"Элемент с индексом {index}: {color}")
Генераторы списков (List Comprehensions)
Это элегантный и "питонический" способ создавать списки на основе других последовательностей.
Простейшие генераторы
Синтаксис: [выражение for элемент in последовательность]
# Создание списка чисел от 0 до 9
numbers = [i for i in range(10)]
print(numbers) # [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
# Создание списка квадратов
squares = [x**2 for x in range(1, 6)]
print(squares) # [1, 4, 9, 16, 25]
Генераторы с условием (фильтрацией)
Синтаксис: [выражение for элемент in последовательность if условие]
# Создать список только четных чисел от 0 до 10
even_numbers = [x for x in range(11) if x % 2 == 0]
print(even_numbers) # [0, 2, 4, 6, 8, 10]
# Создать список длин строк, которые длиннее 3 символов
words = ["apple", "cat", "window", "dog"]
long_word_lengths = [len(word) for word in words if len(word) > 3]
print(long_word_lengths) # [5, 6]
Встроенные функции для работы со списками
функция len() — длина списка
my_list = [10, 20, 30]
print(len(my_list)) # 3
функция sum() — сумма элементов
Работает только для списков, содержащих числа.
numbers = [1, 2, 3, 4, 5]
print(sum(numbers)) # 15
функция max() и min()
Находят максимальный и минимальный элементы в списке.
numbers = [10, 5, 100, -2]
print(f"Максимум: {max(numbers)}") # 100
print(f"Минимум: {min(numbers)}") # -2
функция zip()
Объединяет несколько списков в один, создавая пары (кортежи) из элементов с одинаковыми индексами.
names = ["Анна", "Борис", "Виктор"]
ages = [25, 30, 35]
zipped_data = zip(names, ages)
print(list(zipped_data)) # [('Анна', 25), ('Борис', 30), ('Виктор', 35)]
функция map()
Применяет функцию к каждому элементу списка. Возвращает итератор.
numbers = [1, 2, 3, 4]
# Применить функцию str ко всем элементам, чтобы превратить их в строки
string_numbers = map(str, numbers)
print(list(string_numbers)) # ['1', '2', '3', '4']
функция filter()
Фильтрует список, оставляя только те элементы, для которых функция-условие возвращает True.
def is_positive(n):
return n > 0
numbers = [-10, 5, 0, -2, 8]
positive_numbers = filter(is_positive, numbers)
print(list(positive_numbers)) # [5, 8]
Дополнительные задачи и примеры
Поворот списка (сдвиг элементов)
Задача: сдвинуть список [1, 2, 3, 4, 5] на 2 элемента влево, чтобы получилось [3, 4, 5, 1, 2].
Решение через срезы
Это самый простой и элегантный способ.
my_list = [1, 2, 3, 4, 5]
shift = 2
# Соединяем срез, начиная со сдвига, со срезом до сдвига
rotated_list = my_list[shift:] + my_list[:shift]
print(rotated_list) # [3, 4, 5, 1, 2]
Удаление дубликатов с помощью множества (set)
Множества (set) в Python не могут содержать дубликатов. Преобразовав список в множество и обратно, можно легко удалить все повторы. Порядок элементов при этом может не сохраниться.
numbers_with_duplicates = [1, 2, 3, 2, 4, 1, 5, 5]
# Преобразуем в множество, чтобы удалить дубликаты, и обратно в список
unique_numbers = list(set(numbers_with_duplicates))
print(unique_numbers) # [1, 2, 3, 4, 5] (порядок может быть другим)
Разделение списка на части (чанки)
Задача: разделить список [1, 2, 3, 4, 5, 6, 7, 8] на чанки размером 3.
long_list = [1, 2, 3, 4, 5, 6, 7, 8]
chunk_size = 3
# Используем генератор и срезы
chunks = [long_list[i:i + chunk_size] for i in range(0, len(long_list), chunk_size)]
print(chunks) # [[1, 2, 3], [4, 5, 6], [7, 8]]
Преобразование списка списков в плоский список
Задача: превратить [[1, 2], [3, 4], [5]] в [1, 2, 3, 4, 5].
nested_list = [[1, 2], [3, 4], [5]]
# Используем вложенный генератор списков
flat_list = [item for sublist in nested_list for item in sublist]
print(flat_list) # [1, 2, 3, 4, 5]