python list

¿Por qué Python comienza en el índice-1(en lugar de 0) al indexar una lista desde el final?



(7)

Esta pregunta ya tiene una respuesta aquí:

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


Este es el método mnemotécnico que utilizo. Es solo un enfoque de lo que está sucediendo, pero funciona.

No pienses en esos como índices. Piense en ellos como compensaciones en una lista circular.

Usemos la lista x = [a, b, c, d, e, f, g, h] como ejemplo. Piensa en x [2] yx [-2]:

Empiezas en el offset cero. Si avanza dos pasos, va de a a b (0 a 1), y de b a c (1 a 2).

Si mueve dos pasos hacia atrás, va de a a h (0 a -1), y luego de h a g (-1 a -2)


Este lenguaje puede ser justificado usando aritmética modular. Podemos pensar que los índices se refieren a una celda en una lista obtenida al avanzar elementos i . -1 refiriéndose al último elemento de la lista es una generalización natural de esto, ya que llegamos al último elemento de la lista si retrocedemos un paso desde el inicio de la lista.

Para cualquier lista xs e índice i positivo o negativo , la expresión

xs[i]

tendrá el mismo valor que la expresión a continuación o producirá un IndexError :

xs[i % len(xs)]

El índice del último elemento es -1 + len(xs) que es congruente con -1 mod len(xs) . Por ejemplo, en una matriz de longitud 12, el índice canónico del último elemento es 11. 11 es congruente con -1 mod 12.

Sin embargo, en Python, las matrices se usan más a menudo como estructuras de datos lineales que las circulares , por lo que los índices más grandes que -1 + len(xs) o más pequeños que -len(xs) están fuera de límites, ya que rara vez hay una necesidad para ellos y los efectos serían realmente contradictorios si el tamaño de la matriz cambiara alguna vez.


Otra explicación:

Tu dedo apunta al primer elemento. El índice decide cuántos lugares cambia el dedo hacia la derecha. Si el número es negativo, mueve el dedo hacia la izquierda.

Por supuesto, no puede avanzar a la izquierda desde el primer elemento, por lo que el primer paso a la izquierda se ajusta al último elemento.


Para explicarlo de otra manera, porque -0 es igual a 0 , si el retroceso comienza desde 0 , es ambiguo para el intérprete.

Si estás confundido acerca de, y si buscas otra forma de indexar hacia atrás de manera más comprensible, puedes probar ~ , es un espejo de adelante:

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

Los usos típicos para ~ son como "swap mirror node" o "find median in a sort list":

"""swap mirror node""" def reverse(arr: List[int]) -> None: for i in range(len(arr) // 2): arr[i], arr[~i] = arr[~i], arr[i] """find median in a sort list""" def median(arr: List[float]) -> float: mid = len(arr) // 2 return (arr[mid] + arr[~mid]) / 2 """deal with mirror pairs""" # verify the number is strobogrammatic, strobogrammatic number looks the same when rotated 180 degrees def is_strobogrammatic(num: str) -> bool: return all(num[i] + num[~i] in ''696 00 11 88'' for i in range(len(num) // 2 + 1))

~ realidad es un truco matemático de código inverso y código de complemento, y es más fácil de entender en algunas situaciones.

Discusión sobre si se deben usar trucos de Python como ~ :

En mi opinión, si se trata de un código mantenido por usted mismo, puede utilizar cualquier truco para evitar posibles errores o lograr un objetivo más fácil, debido a la alta legibilidad y facilidad de uso. Pero en el trabajo en equipo, evite usar el código ''demasiado inteligente'' , puede traer problemas a sus compañeros de trabajo.

Por ejemplo, aquí hay un código conciso de Stefan Pochmann para resolver este problema . Aprendí mucho de su código. Pero algunos son solo por diversión, demasiado piratas para usar.

# a strobogrammatic number is a number that looks the same when rotated 180 degrees (looked at upside down) # find all strobogrammatic numbers that are of length = n 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

He resumido trucos de Python como este, en caso de que esté interesado.


Podrías entenderlo intuitivamente de esta manera.

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

Supongamos que comienzas de a a d , a es tu punto de partida donde te encuentras (o tu hogar), así que márcalo como 0 (porque aún no te has movido),

Mueva un paso a b, el segundo paso a c y llegue al tercero d.

Entonces, ¿qué tal si regresa de d a (o regresa de su oficina a su hogar)? Su hogar es 0 porque su familia vive allí, por lo que su oficina no puede ser un 0 Es su última parada.

Así que cuando vuelvas a casa. d es la última primera parada hacia donde empiezas para el hogar, c es el último segundo ....


Porque -0 en Python es 0 .
Con 0 obtienes el primer elemento de la lista y
con -1 obtienes el último elemento de la lista

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

También puede pensarlo como una abreviatura para la list[len(list) - x] donde x es la posición del elemento desde la parte posterior. Esto es válido solo si 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


list[-1]

Es mano corta para:

list[len(list)-1]

La parte de len(list) es implícita. Por eso el -1 es el último elemento. Eso se aplica a cualquier índice negativo: la resta de len(list) siempre está implícita