Индекс в Python — это целое число, номер позиции элемента в упорядоченной последовательности: списке, строке, кортеже, range. Отсчет идет с нуля, а отрицательные индексы считают с конца: -1 — последний элемент. По индексу элемент читают (lst[2]), а метод index() решает обратную задачу — по значению находит позицию.
Содержание
Ниже — как обращаться к элементам по индексу, как искать позицию через index(), как брать части последовательности срезами и как перебирать элементы вместе с их номерами. Все примеры прогнаны на Python 3.14.7 (24.09.2026).
Четыре понятия, которые легко спутать
| Понятие | Синтаксис | Что дает | Если не получилось |
|---|---|---|---|
| Индекс (обращение по позиции) | lst[i] |
один элемент | IndexError |
Метод index() (поиск позиции) |
lst.index(x) |
номер первого вхождения x |
ValueError |
| Срез | lst[a:b:step] |
новую последовательность-копию части | ошибки нет, может быть пусто |
enumerate() (перебор с номером) |
for i, x in enumerate(lst) |
пары (номер, элемент) | — |
Главное различие: индекс — это позиция, а index() — это поиск. Выражение fruits[2] работает мгновенно и не зависит от длины списка, а fruits.index("cherry") просматривает элементы по очереди, пока не найдет совпадение.
Минимальный пример целиком
fruits = ["apple", "banana", "cherry", "banana", "kiwi"]
print(fruits[0]) # первый элемент
print(fruits[-1]) # последний
print(fruits.index("banana")) # позиция первого вхождения
print(fruits.index("banana", 2)) # искать начиная с индекса 2
print(fruits[1:3]) # срез: индексы 1 и 2
for i, name in enumerate(fruits, start=1):
print(i, name)
Результат:
apple
kiwi
1
3
['banana', 'cherry']
1 apple
2 banana
3 cherry
4 banana
5 kiwi
Разбор по строкам: fruits[0] берет элемент на позиции 0, fruits[-1] — последний. Метод index("banana") возвращает 1, потому что это первое вхождение, хотя «banana» встречается дважды. Со вторым аргументом поиск начинается с позиции 2, и находится второе вхождение — 3. Срез [1:3] включает индекс 1 и не включает 3. Наконец, enumerate(..., start=1) нумерует элементы с единицы — удобно для вывода человеку, но сами индексы списка от этого не меняются.
Положительные и отрицательные индексы
Для строки "Python" индексы выглядят так:
P y t h o n
0 1 2 3 4 5
-6 -5 -4 -3 -2 -1
Отрицательный индекс — это сокращение для len(s) + i: s[-2] то же, что s[4]. Допустимые индексы для последовательности длины n — от -n до n - 1. Все, что за этими границами, дает ошибку.
nums = [10, 20, 30, 40, 50]
print(nums[5])
Traceback (most recent call last):
File "<stdin>", line 2, in <module>
IndexError: list index out of range
В списке 5 элементов, значит последний индекс 4, а не 5. Исправление — брать nums[-1] или nums[len(nums) - 1]. Для строки текст ошибки другой (string index out of range), для индекса-дроби — TypeError: list indices must be integers or slices, not float.
Строку по индексу можно прочитать, но нельзя изменить — строки неизменяемы:
s = "Python"
try:
s[0] = "J"
except TypeError as e:
print("TypeError:", e)
s = "J" + s[1:] # исправление: собрать новую строку
print(s)
TypeError: 'str' object does not support item assignment
Jython
Граница применимости: индексы по позиции есть у последовательностей (list, str, tuple, range, bytes). У словаря в квадратных скобках пишут ключ, а не позицию, а у множества (set) порядка и индексов нет вовсе.
Метод index(): найти позицию по значению
Сигнатура: seq.index(value, start, end), где start и end необязательны и ограничивают участок поиска так же, как срез. Метод есть у списков, кортежей и строк; для строки он ищет подстроку. Возвращается позиция первого вхождения.
Если значения нет, метод не возвращает -1, а выбрасывает исключение:
fruits = ["apple", "banana"]
print(fruits.index("mango"))
Traceback (most recent call last):
File "<stdin>", line 2, in <module>
ValueError: list.index(x): x not in list
Исправление зависит от задачи. Если отсутствие элемента — обычная ситуация, удобна функция с явным значением по умолчанию:
def find_index(seq, value, default=-1):
try:
return seq.index(value)
except ValueError:
return default
fruits = ["apple", "banana", "cherry"]
print(find_index(fruits, "cherry")) # 2
print(find_index(fruits, "mango")) # -1
s = "python"
print(s.find("th"), s.find("zz")) # 2 -1
Вариант с проверкой if name in fruits: перед index() тоже рабочий, но проходит список дважды. У строк есть готовый find(), который возвращает -1 без исключения; у списков метода find() нет. Осторожно с -1 как признаком «не найдено»: это валидный индекс последнего элемента, поэтому результат find() нельзя сразу подставлять в s[...] без проверки.
Метод index() находит только первое вхождение. Все позиции собирают через enumerate:
nums = [3, 8, 5, 8, 1]
positions = [i for i, x in enumerate(nums) if x == 8]
print(positions) # [1, 3]
Поиск через index() линейный: в худшем случае просматриваются все n элементов. Если по значению ищут часто и в большом списке, обычно заводят словарь «значение -> позиция».
Срезы: [start:stop:step]
Срез берет часть последовательности. start входит в результат, stop — нет, step задает шаг. Любой параметр можно пропустить: тогда берется начало, конец или шаг 1.
| Выражение | s = "Python" |
nums = [0..9] |
|---|---|---|
[1:4] |
yth |
[1, 2, 3] |
[:2] |
Py |
[0, 1] |
[2:] |
thon |
[2, 3, ..., 9] |
[-3:] |
hon |
[7, 8, 9] |
[::2] |
Pto |
[0, 2, 4, 6, 8] — четные позиции |
[1::2] |
yhn |
[1, 3, 5, 7, 9] — нечетные позиции |
[::-1] |
nohtyP |
список в обратном порядке |
Три отличия среза от обращения по индексу. Первое: выход за границы не вызывает ошибку — nums[7:100] вернет [7, 8, 9], а nums[3:1] вернет пустой список. Второе: срез создает новый объект, исходный не меняется. Третье: копия поверхностная — вложенные объекты общие.
a = [1, 2, 3]
b = a[:]
b[0] = 99
print(a, b) # [1, 2, 3] [99, 2, 3]
row = [1, 2]
m = [row, [3, 4]]
c = m[:]
c[0][0] = 99
print(m[0]) # [99, 2] - вложенный список общий
Для вложенных структур нужна copy.deepcopy(). У списков срезу можно присвоить значение: a[1:3] = ["x"] заменит два элемента одним, а del a[::2] удалит каждый второй.
Перебор: элементы, индексы или и то и другое
Выбор способа зависит от того, что нужно внутри цикла:
| Задача | Что взять |
|---|---|
| Нужны только значения | for x in lst |
| Нужны номер и значение | for i, x in enumerate(lst) |
| Нужно менять элементы по месту | for i in range(len(lst)): lst[i] = ... |
| Идти параллельно по двум спискам | for a, b in zip(xs, ys) |
| Условие остановки не связано с длиной | while с явным счетчиком |
letters = ["a", "b", "c"]
for i, ch in enumerate(letters):
print(i, ch)
names = ["Ann", "Bob", "Kate"]
scores = [90, 75, 88]
for name, score in zip(names, scores):
print(name, score)
0 a
1 b
2 c
Ann 90
Bob 75
Kate 88
Запись for i in range(len(letters)) дает тот же результат, что enumerate, но длиннее и легче ошибиться в индексе. zip останавливается на самом коротком списке, лишние элементы длинного молча отбрасываются. while требует ручного счетчика: забытый i += 1 превращает его в бесконечный цикл.
Типичная ошибка: удаление во время перебора
nums = [1, 2, 2, 3, 4]
for i in range(len(nums)):
if nums[i] % 2 == 0:
del nums[i]
Traceback (most recent call last):
File "<stdin>", line 3, in <module>
IndexError: list index out of range
range(len(nums)) вычислен один раз для 5 элементов, а список укорачивается. Вариант for x in nums: с if x % 2 == 0: nums.remove(x) внутри не падает, но молча пропускает элементы: на том же входе останется [1, 2, 3] вместо [1, 3]. Исправление — собрать новый список:
nums = [1, 2, 2, 3, 4]
nums = [x for x in nums if x % 2 != 0]
print(nums) # [1, 3]
Если не получилось: симптом -> причина
| Симптом | Частая причина | Что сделать |
|---|---|---|
IndexError: list index out of range |
индекс равен длине или больше | последний элемент — len - 1 или -1 |
ValueError: ... not in list |
index() не нашел значение |
try/except или проверка in |
TypeError: list indices must be integers |
индекс — строка или дробь | int(...), для деления // |
| Срез вернул пустой список | start правее stop при шаге 1 |
поменять границы или задать step=-1 |
| Цикл пропускает элементы | список меняется во время перебора | новый список через генератор списка |
Выводы
- Индекс — позиция элемента с отсчетом от нуля; отрицательный индекс считает с конца, допустимый диапазон от
-lenдоlen - 1. index()ищет позицию по значению, возвращает первое вхождение и выбрасываетValueError, если значения нет;find()с-1есть только у строк.- Срез
[start:stop:step]не включаетstop, не падает при выходе за границы и возвращает поверхностную копию. - Для перебора с номером берут
enumerate, для параллельного прохода —zip; изменять список внутри цикла по нему же нельзя.
Где применяется / связь с практикой
Индексы и срезы встречаются почти в любом коде на Python: разбор строк и файлов, обработка ответов API, подготовка данных для анализа, алгоритмические задачи на собеседованиях. На них же строится работа с массивами NumPy и таблицами pandas, где правила срезов похожие, но есть свои отличия.
Освойте тему на практике
Если хочется разобрать эти основы последовательно, с практикой и проверкой кода, подойдет курс «Python-разработчик. Базовый уровень». Бесплатно посмотреть формат занятий можно на открытых уроках Otus.
FAQ
Почему индексы в Python начинаются с нуля?
Индекс удобно понимать как смещение от начала последовательности: у первого элемента смещение 0. Так же устроены C, Java и большинство популярных языков, а срезы вида s[:n] при этом дают ровно n элементов.
Как получить индекс максимального элемента списка?
Самый читаемый способ — nums.index(max(nums)): он вернет позицию первого максимума, но пройдет список дважды. За один проход — max(range(len(nums)), key=nums.__getitem__).
Можно ли обращаться к словарю по индексу?
Нет: d[0] ищет ключ 0. Словари сохраняют порядок вставки, поэтому при необходимости можно сделать list(d)[0], но это создает список всех ключей.



