Python: уроки, справочник и задачи

Операции со списками в Python на примерах

Раздел: Списки, кортежи и множества · Обновлено 31.10.2026

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

Операции со списками в Python на примерах
Фото: M.O. Stevens / CC BY-SA 3.0, Wikimedia Commons
Содержание статьи
  1. Индексы и перебор с номером элемента
  2. Срезы
  3. Сложение, повторение и распаковка
  4. Проверка вхождения, длина и сравнение
  5. Удаление элементов и дубликатов
  6. Сводная таблица операций
  7. Частые вопросы
    1. Как получить последний элемент списка?
    2. Чем a + b отличается от a.extend(b)?
    3. Как скопировать список, чтобы изменения не затронули оригинал?
    4. Как развернуть список?

Индексы и перебор с номером элемента

Элементы списка нумеруются с нуля, обращение идет через квадратные скобки. Отрицательный индекс отсчитывает с конца: -1 означает последний элемент, -2 предпоследний. Индекс за пределами списка вызывает IndexError.

nums = [21, 44, 35, 11]
print(nums[0], nums[-1])   # 21 11
nums[1] = 50               # список изменяемый
print(nums)                # [21, 50, 35, 11]

Когда при переборе нужен и номер, и значение, используют функцию enumerate(). Она выдает пары (индекс, элемент), а параметр start задает начальный номер, если нумерация нужна не с нуля.

nums = [21, 44, 35, 11]
for i, val in enumerate(nums, start=1):
    print(i, val)
# 1 21
# 2 44
# 3 35
# 4 11

Вариант с range(len(nums)) тоже работает, но читается хуже и требует лишнего обращения по индексу внутри цикла.

Срезы

Срез возвращает новый список из части элементов. Синтаксис список[start:stop:step]: start включается, stop нет, step задает шаг. Любую из трех частей можно пропустить, тогда берутся значения по умолчанию: начало, конец и шаг 1.

a = [1, 2, 3, 4, 5]
print(a[2:])     # [3, 4, 5]  с индекса 2 до конца
print(a[:2])     # [1, 2]     до индекса 2, не включая его
print(a[1:4])    # [2, 3, 4]
print(a[::2])    # [1, 3, 5]  каждый второй
print(a[::-1])   # [5, 4, 3, 2, 1]  в обратном порядке
print(a[-2:])    # [4, 5]     два последних

В отличие от индекса, срез не вызывает ошибку при выходе за границы: a[3:100] просто вернет [4, 5]. Срезу можно и присвоить значение, тогда часть списка заменится: a[1:3] = ["x"] превратит список в [1, "x", 4, 5]. Подробно о шаге и отрицательных границах написано в статье про срезы.

Сложение, повторение и распаковка

Оператор + склеивает два списка в новый, исходные не меняются. Оператор * с целым числом повторяет содержимое нужное число раз. Оба работают только между списками: [1] + (2,) вызовет TypeError.

a = [1, "a"]
b = [3, 4, 5]
print(a + b)        # [1, 'a', 3, 4, 5]
print([0] * 4)      # [0, 0, 0, 0]
print([*a, *range(2, 4)])  # [1, 'a', 2, 3]
a += b              # дописывает b в конец a на месте

Распаковка через звездочку внутри квадратных скобок собирает список из любых итерируемых объектов: других списков, кортежей, диапазонов, строк. Это удобнее, чем сначала приводить каждый объект к списку.

С повторением вложенных списков есть ловушка. Выражение [[0] * 3] * 2 создаст две ссылки на один и тот же внутренний список, и изменение одной строки изменит обе. Для матриц пишут генератор: [[0] * 3 for _ in range(2)].

Проверка вхождения, длина и сравнение

Оператор in проверяет, есть ли значение в списке, not in проверяет обратное. Поиск идет перебором слева направо, поэтому на больших списках при частых проверках выгоднее множество.

langs = ["python", "go", "rust"]
print("go" in langs)       # True
print("java" not in langs) # True
print(len(langs))          # 3
print(min([4, 1, 7]), max([4, 1, 7]), sum([4, 1, 7]))  # 1 7 12

Списки сравниваются поэлементно, как слова в словаре: первая пара различающихся элементов определяет результат. Оператор == проверяет равенство содержимого, а is проверяет, что это один и тот же объект в памяти.

print([1, 2, 3] < [1, 3])   # True, 2 < 3
x = [1, 2]
y = [1, 2]
print(x == y, x is y)       # True False

Удаление элементов и дубликатов

Инструкция del удаляет элемент по индексу или целый срез. В отличие от метода pop(), она ничего не возвращает. Остальные способы удаления, включая remove() и clear(), описаны в обзоре методов списка.

a = [10, 20, 30, 40, 50]
del a[0]      # [20, 30, 40, 50]
del a[1:3]    # [20, 50]

Чтобы убрать повторы, список превращают во множество и обратно. Способ короткий, но порядок элементов после set() не гарантируется. Если порядок важен, используют dict.fromkeys(): ключи словаря уникальны и хранятся в порядке добавления.

data = [3, 1, 3, 2, 1]
print(list(set(data)))            # порядок может быть любым
print(list(dict.fromkeys(data)))  # [3, 1, 2]

a, b = [1, 2, 4, 6], [7, 8, 2, 1]
print(sorted(set(a) | set(b)))    # объединение без повторов: [1, 2, 4, 6, 7, 8]
print(sorted(set(a) ^ set(b)))    # только в одном из списков: [4, 6, 7, 8]

Другие способы, включая удаление повторов в списке словарей, собраны в статье об удалении дубликатов.

Сводная таблица операций

Ниже перечислены операции, которые работают со списком без вызова методов, и их сложность для списка длины n.

ОперацияПримерРезультатСложность
Индексa[i]элементO(1)
Срезa[i:j]новый списокO(j-i)
Сложениеa + bновый списокO(n+m)
Повторениеa * kновый списокO(n*k)
Вхождениеx in aboolO(n)
Длинаlen(a)intO(1)
Удалениеdel a[i]изменяет aO(n)

Удаление из начала списка дорогое, потому что все последующие элементы сдвигаются. Если элементы часто снимаются с обоих концов, лучше подходит collections.deque.

Частые вопросы

Короткие ответы на вопросы, которые возникают при работе со списками.

Как получить последний элемент списка?

Через отрицательный индекс: a[-1]. Для пустого списка это вызовет IndexError, поэтому перед обращением проверяют if a:.

Чем a + b отличается от a.extend(b)?

a + b создает новый список, а оба исходных остаются прежними. extend() и оператор += меняют список a на месте, это быстрее и не требует лишней памяти.

Как скопировать список, чтобы изменения не затронули оригинал?

Срез a[:], a.copy() или list(a) создают поверхностную копию. Для вложенных списков нужен copy.deepcopy(), иначе внутренние списки останутся общими.

Как развернуть список?

Срез a[::-1] вернет новый перевернутый список, метод a.reverse() развернет существующий на месте, а reversed(a) даст итератор для перебора в обратном порядке.