Почему Python начинается с индекса -1 (вместо 0) при индексации списка с конца?

list = ["a", "b", "c", "d"]
print(list[3]) # Number 3 is "d"

print(list[-4]) # Number -4 is "a"

Ответ 1

Чтобы объяснить это по-другому, потому что -0 равен 0, если обратное начинается с 0, это неоднозначно для интерпретатора.


Если вы не понимаете - и ищете более понятный способ индексации назад, вы можете попробовать ~, это зеркало продвижения вперед:

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

Типичные случаи использования ~ похожи на "swap mirror node" или "найти медиану в списке сортировки":

def reverse(arr):
    for i in range(len(arr)//2):
        arr[i], arr[~i] = arr[~i], arr[i]

def median(arr):
    mid = len(arr) // 2
    return (arr[mid] + arr[~mid]) / 2

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


Обсуждение о том, следует ли использовать Python трюки, такие как ~:

На мой взгляд, если это код, поддерживаемый вами, вы можете использовать любой прием, чтобы избежать потенциальной ошибки или легче достичь цели, возможно, из-за высокой читабельности и удобства использования. Но в командной работе избегайте использования "слишком умного" кода, это может доставить неприятности вашим коллегам.

Например, вот один краткий код от Стефана Покмана для решения этой проблемы. Я многому научился по его коду. Но некоторые просто для удовольствия, слишком хакерские для использования.

def findStrobogrammatic(self, n):
    nums = n % 2 * list('018') or ['']
    while n > 1:
        n -= 2
        # n < 2 is so genius here
        nums = [a + num + b for a, b in '00 11 88 69 96'.split()[n < 2:] for num in nums]
    return nums

Ответ 2

list[-1]

Это короткая рука для:

list[len(list)-1]

Часть len(list) неявная. Вот почему -1 является последним элементом. Это относится к любому отрицательному индексу - вычитание из len(list) всегда неявно

Ответ 3

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


Не думайте о них как об индексах. Думайте о них как о смещениях в круговом списке.

Давайте использовать список x = [a, b, c, d, e, f, g, h] в качестве примера. Подумайте о х [2] и х [-2]:

enter image description here

Вы начинаете со смещения нуля. Если вы продвинетесь на два шага вперед, вы перейдете от a к b (от 0 до 1) и от b к c (от 1 до 2).

Если вы переместитесь на два шага назад, вы перейдете от a к h (от 0 до -1), а затем от h к g (-1 до -2)

Ответ 4

Потому что -0 в Python равен 0.
С 0 вы получаете первый элемент списка и
с помощью -1 вы получите последний элемент списка

list = ["a", "b", "c", "d"]
print(list[0]) # "a"
print(list[-1]) # d

Вы также можете считать это сокращением для list[len(list) - x] где x - позиция элемента сзади. Это действительно, только если 0 < -(-x) < len(list)

print(list[-1]) # d
print(list[len(list) - 1]) # d
print(list[-5]) # list index out of range
print(list[len(list) - 5]) # a

Ответ 5

Эта идиома может быть обоснована с помощью модульной арифметики. Мы можем думать об индексах как о ссылке на ячейку в списке, полученном при переходе вперед i элементов. -1 ссылка на последний элемент списка является естественным обобщением этого, так как мы достигаем последнего элемента в списке, если мы идем назад на один шаг от начала списка.

Для любого списка xs и индекса i положительного или отрицательного, выражение

xs[i]

либо будет иметь то же значение, что и выражение ниже, либо IndexError:

xs[i % len(xs)]

Индекс последнего элемента равен -1 + len(xs) который соответствует -1 mod len(xs). Например, в массиве длиной 12 канонический индекс последнего элемента равен 11. 11 соответствует -1 mod 12.

В Python, однако, массивы чаще используются в качестве линейных структур данных, чем циклических, поэтому индексы, большие, чем -1 + len(xs) или меньшие, чем -len(xs), выходят за пределы, поскольку в них редко есть необходимость и эффекты были бы действительно нелогичными, если бы размер массива когда-либо изменился.

Ответ 6

Другое объяснение:

Ваш палец указывает на первый элемент. Индекс решает, сколько мест вы сдвинете пальцем вправо. Если число отрицательное, вы перемещаете палец влево.

Конечно, вы не можете сделать шаг влево от первого элемента, поэтому первый шаг влево переходит к последнему элементу.

Ответ 7

Вы могли бы интуитивно понять это таким образом

steps= ["a", "b", "c", "d"]

Предположим, вы начинаете с a до d, a - это ваша начальная точка, где вы стоите (или ваш дом), поэтому отметьте его как 0 (потому что вы не двигаетесь),

Переместите один шаг к b, второй шаг к c и достигните третьего d.

Тогда как насчет того, чтобы вернуться из d в (или вернуться из своего офиса к себе домой). Ваш дом равен 0 потому что там живет ваша семья, поэтому ваш офис не может быть 0 Это ваша последняя остановка.

Поэтому, когда вы вернетесь домой. d - последняя первая остановка, c - последняя секунда....

Ответ 8

Вот подробная документация по индексам списков в Python, пожалуйста, посмотрите на это. питон-список-индекс

Ответ 9

В комментарии Авраам спросил

Я бы хотел, чтобы у python был другой механизм для получения списка в обратном направлении.

Для другого способа получить доступ к спискам в обратном направлении, можно сначала просто перевернуть список, а затем получить доступ к элементам, как обычно:

lst = ["a", "b", "c", "d"]
print(lst[::-1][0])   # "d"
print(lst[::-1][1])   # "c"