Перейти к содержимому

Типовые задачи с последовательностями в Python [2.6]

Типовые задачи с последовательностями в Python [2.6]

Индексация, срезы, преобразования типов последовательностей и сортировка: понятные правила, типовые рецепты и распространённые ошибки. В конце — практические задания и чек‑лист самопроверки.

Последовательности (например, list, tuple, str, range) поддерживают общий набор операций: индексацию s[i], срезы s[start:stop:step] и сортировку (прямо или через преобразование в список).

Содержание

1. Цели урока

  • Узнать, как работает индексация и как уверенно доставать элементы.
  • Научиться делать срезы ([start:stop:step]) и понимать их правила.
  • Познакомиться с преобразованиями между типами последовательностей: list(), tuple().
  • Научиться сортировать: sorted(), list.sort(), key, reverse.
Что особенно важно запомнить: срезы используют те же индексы, что и range(start, stop, step), а граница stop никогда не включается.
↑ К оглавлению

2. Что такое последовательности и что в них “типового”

Последовательность — это упорядоченный набор элементов, у которого обычно есть длина и поддерживается доступ по индексу. К типичным последовательностям относятся: list, tuple, str, range.

lst = [10, 20, 30]      # список
tup = (10, 20, 30)      # кортеж
s = "python"            # строка — тоже последовательность символов
r = range(5)            # ленивое "как бы последовательность" чисел

Чем отличаются set и dict

set — неупорядоченная структура: индексации и срезов нет. dict — отображение ключ→значение: доступ идёт по ключу, а не по позиции.

Запомните: срезы — это про упорядоченность. Если порядок не определён (как в set), то и “кусок по индексам” невозможен.
↑ К оглавлению

3. Индексация: как доставать элементы

s[i] и базовые правила

Индексация в Python начинается с нуля: s[0] — первый элемент, s[1] — второй и т.д.

arr = ["a", "b", "c", "d"]
print(arr[0])  # a
print(arr[2])  # c

Отрицательные индексы

Отрицательные индексы считаются от конца: -1 — последний элемент, -2 — предпоследний и т.д.

arr = ["a", "b", "c", "d"]
print(arr[-1])  # d
print(arr[-2])  # c

Типовые задачи на индексацию

Задача: первый и последний

arr = [10, 20, 30, 40]
first = arr[0]
last = arr[-1]
print(first, last)  # 10 40

Задача: заменить элемент (только list)

arr = [10, 20, 30]
arr[1] = 999
print(arr)  # [10, 999, 30]

Кортеж (tuple) неизменяем, так не получится.

Типичные ошибки индексации

Ошибка 1: IndexError — вышли за границы

arr = [1, 2, 3]
# print(arr[3])  # IndexError: list index out of range
Если не уверены в границах, часто безопаснее использовать срез: arr[3:4] вернёт пустой список вместо ошибки.
↑ К оглавлению

4. Срезы (slicing): как брать “кусок” последовательности

Синтаксис [start:stop:step]

Срез — это способ получить часть последовательности. Общая форма: [start:stop:step]. Граница stop не включается.

arr = [0, 1, 2, 3, 4, 5]
print(arr[1:4])   # [1, 2, 3] (4 не включается)
print(arr[:3])    # [0, 1, 2]
print(arr[3:])    # [3, 4, 5]

Значения по умолчанию

  • start по умолчанию: начало последовательности.
  • stop по умолчанию: конец последовательности.
  • step по умолчанию: 1.
  • Отрицательные значения поддерживаются.
  • -1 в индексации означает “последний элемент”.
Важно: срезы используют те же индексы, что и range(start, stop, step). Это помогает понимать, какие позиции будут выбраны.

Срез со шагом

arr = list(range(10))
print(arr[::2])   # [0, 2, 4, 6, 8]
print(arr[1::2])  # [1, 3, 5, 7, 9]
print(arr[2:9:3]) # [2, 5, 8]

Отрицательный шаг и разворот

Если step отрицательный, срез идёт справа налево. Самый популярный приём — развернуть список: s[::-1].

arr = [1, 2, 3, 4]
print(arr[::-1])  # [4, 3, 2, 1]

Типовые рецепты со срезами

Первые N / последние N

arr = [10, 20, 30, 40, 50]
print(arr[:2])   # [10, 20]
print(arr[-2:])  # [40, 50]

Срезы “мягкие”: если N больше длины, ошибки не будет.

Без первого и последнего

arr = [10, 20, 30, 40, 50]
print(arr[1:-1])  # [20, 30, 40]

Копия списка через срез

a = [1, 2, 3]
b = a[:]          # поверхностная копия
print(a, b)       # [1, 2, 3] [1, 2, 3]
Это поверхностная копия: если внутри списка лежат изменяемые объекты, они не копируются “глубоко”.

Срез-присваивание (только list)

Списки изменяемы, поэтому можно заменять “кусок” списка другим набором элементов.

arr = [0, 1, 2, 3, 4, 5]
arr[2:4] = [200, 300, 400]
print(arr)
# [0, 1, 200, 300, 400, 4, 5]

Типичные ошибки со срезами

Ошибка 1: ожидать, что stop включается

arr = [0, 1, 2, 3, 4]
print(arr[1:3])  # [1, 2], а не [1, 2, 3]

Ошибка 2: перепутать границы при отрицательном шаге

arr = [0, 1, 2, 3, 4]
print(arr[1:4:-1])  # [] — идём назад, но stop "не в ту сторону"
print(arr[4:1:-1])  # [4, 3, 2]
При step < 0 срез движется справа налево. Указывайте start справа, а stop левее.
↑ К оглавлению

5. Преобразование типов последовательностей

Конструкторы list(iterable) и tuple(iterable) принимают любой итерируемый объект: список, кортеж, строку, генератор, range и т.д. Они перебирают элементы и создают новую структуру.

print(list("abc"))        # ['a', 'b', 'c']
print(tuple([1, 2, 3]))   # (1, 2, 3)
print(list(range(5)))     # [0, 1, 2, 3, 4]
Зачем конвертировать?
  • Нужна изменяемость — делаем list(...).
  • Нужна неизменяемость (например, чтобы использовать как ключ словаря) — делаем tuple(...).
  • Нужно “материализовать” ленивый объект (например, range или генератор) — делаем list(...).

Копирование: a[:] vs list(a)

a = [1, 2, 3]
b1 = a[:]        # копия срезом
b2 = list(a)     # копия через конструктор
print(b1, b2)    # [1, 2, 3] [1, 2, 3]

Типичные ошибки преобразования

Ошибка: ожидать “глубокую” копию

И a[:], и list(a) делают поверхностную копию. Если внутри лежат списки, то вложенные списки будут общими.

a = [[1], [2]]
b = a[:]

b[0].append(999)
print(a)  # [[1, 999], [2]]  изменилось и в a
↑ К оглавлению

6. Сортировка последовательностей

sorted() vs list.sort()

  • sorted(iterable) принимает итерируемый объект и возвращает новый отсортированный список.
  • list.sort() сортирует сам список на месте и возвращает None.
a = [3, 1, 2]

b = sorted(a)
print(a)  # [3, 1, 2]
print(b)  # [1, 2, 3]

a.sort()
print(a)  # [1, 2, 3]

reverse=True

a = [3, 1, 2]
print(sorted(a, reverse=True))  # [3, 2, 1]

Сортировка по ключу: key=...

Аргумент key — функция, которая получает элемент и возвращает “ключ сортировки”. Частый пример: сортировать слова без учёта регистра.

words = ["Python", "java", "Kotlin", "go"]
print(sorted(words, key=str.lower))
# ['go', 'java', 'Kotlin', 'Python']

Стабильность сортировки

Сортировка в Python стабильна: если ключи равны, элементы сохраняют исходный порядок. Это позволяет делать многошаговую сортировку.

data = [("Ann", 20), ("Bob", 20), ("Chris", 19)]

# Сначала сортируем по имени, потом по возрасту:
data_sorted = sorted(data, key=lambda x: x[0])
data_sorted = sorted(data_sorted, key=lambda x: x[1])

print(data_sorted)
# [('Chris', 19), ('Ann', 20), ('Bob', 20)]

Timsort: почему сортировка часто “умная”

Встроенная сортировка Python использует алгоритм Timsort — гибридный подход, сочетающий идеи сортировки вставками и сортировки слиянием. Он хорошо работает на реальных данных, где часто есть частично упорядоченные фрагменты.

Практический вывод: в реальных проектах почти всегда используйте sorted() или list.sort(), а не самописные сортировки (самописные полезны для обучения).

Типичные ошибки сортировки

Ошибка 1: ждать результат от list.sort()

a = [3, 1, 2]
x = a.sort()
print(x)  # None
print(a)  # [1, 2, 3]

Ошибка 2: пытаться сортировать “несравнимые” типы

items = [1, "2", 3]
# sorted(items)  # TypeError: '<' not supported between instances of 'str' and 'int'
Решение — привести к одному типу (например, к int) или сортировать по ключу, который “унифицирует” сравнение.
↑ К оглавлению

7. Практика: типовые задачи (с решениями)

Задачи на срезы

Задача 1: первые 3, последние 3, без первого и последнего

arr = [10, 20, 30, 40, 50, 60, 70]

print(arr[:3])    # [10, 20, 30]
print(arr[-3:])   # [50, 60, 70]
print(arr[1:-1])  # [20, 30, 40, 50, 60]

Задача 2: каждый 3-й элемент, начиная со второго

arr = list(range(1, 21))
print(arr[1::3])
# [2, 5, 8, 11, 14, 17, 20]

Задачи на индексацию

Задача 3: поменять местами первый и последний элемент (list)

arr = [1, 2, 3, 4, 5]
arr[0], arr[-1] = arr[-1], arr[0]
print(arr)  # [5, 2, 3, 4, 1]

Задачи на сортировку

Задача 4: сортировать слова без учёта регистра

words = ["Python", "java", "Kotlin", "go"]
print(sorted(words, key=str.lower))
# ['go', 'java', 'Kotlin', 'Python']

Задача 5: сортировать (name, age) по age, а при равенстве — по name

people = [("Bob", 20), ("Ann", 20), ("Chris", 19), ("Dan", 19)]

# Вариант 1: одним ключом (кортеж ключей)
res1 = sorted(people, key=lambda x: (x[1], x[0]))
print(res1)
# [('Chris', 19), ('Dan', 19), ('Ann', 20), ('Bob', 20)]

# Вариант 2: два прохода, используя стабильность сортировки
res2 = sorted(people, key=lambda x: x[0])  # вторичный ключ
res2 = sorted(res2, key=lambda x: x[1])    # первичный ключ
print(res2)
# [('Chris', 19), ('Dan', 19), ('Ann', 20), ('Bob', 20)]

Задачи на преобразования типов

Задача 6: сделать список из range и развернуть

r = range(1, 6)
lst = list(r)
print(lst)       # [1, 2, 3, 4, 5]
print(lst[::-1]) # [5, 4, 3, 2, 1]
↑ К оглавлению

8. Чек‑лист самопроверки знаний

Отметьте пункты, которые вы действительно понимаете и можете применить без подсказок.

НавыкПроверка
Индексация последовательностей Могу достать первый, последний, предпоследний элементы через s[0], s[-1], s[-2]
Понимаю границу stop в срезе Могу объяснить, почему s[1:3] включает индексы 1 и 2, но не 3
Срезы со шагом Могу написать s[::2], s[1::2], s[2:9:3]
Разворот последовательности Могу развернуть список/строку через s[::-1] и объяснить, что это отрицательный шаг
Срез-присваивание Могу заменить подотрезок списка: arr[2:4] = ... и понимаю, что это работает только для list
Преобразования типов Могу преобразовать любой iterable в list() или tuple()
sorted() vs list.sort() Могу объяснить, что sorted() возвращает новый список, а sort() сортирует на месте и возвращает None
Сортировка по ключу Могу сортировать без учёта регистра через key=str.lower или сортировать кортежи по полям
Стабильность сортировки Могу сделать многошаговую сортировку (вторичный ключ, затем первичный) и понимаю, почему порядок сохраняется
↑ К оглавлению
Среда, 11 февраля 2026
Типовые задачи с последовательностями в Python [2.6]