python slice reverse

Error de la lista de Python:[::-1] paso en la porción



slice reverse (5)

Cuando escribe [1, 2, 3, ...][1:4:1] es lo mismo que [1, 2, 3, ...][slice(1, 4, 1)] . Entonces 1:4:1 es la abreviatura para el objeto de sector. slice firma del slice es slice(stop) o slice(start, stop[, step]) y también puede usar None para los argumentos.

:: -> slice(None, None, None) :4 -> slice(4) # and so on

Supongamos que tenemos [a: b: c] . Las reglas para los índices serán las siguientes:

  1. La primera c está marcada. El valor predeterminado es +1 , el signo de c indica la dirección hacia adelante o hacia atrás del paso. El valor absoluto de c indica el tamaño del paso.
  2. Que se comprueba una. Cuando c es positivo o None , el valor predeterminado para a es 0 . Cuando c es negativo, el valor predeterminado para a es -1 .
  3. Finalmente se comprueba b . Cuando c es positivo o None , el valor predeterminado para b es len . Cuando c es negativo, el valor predeterminado para b es -(len+1) .

Nota 1 : Los cortes degenerados en Python se manejan con gracia:

  • el índice que es demasiado grande o demasiado pequeño se reemplaza por len o 0 .
  • un límite superior más pequeño que el límite inferior devuelve una lista o cadena vacía o cualquier otra cosa (para c positivo).

Nota 2 : En términos generales, Python recoge elementos mientras esta condición (a < b) if (c > 0) else (a > b) es True (se actualiza a += c en cada paso). Además, todos los índices negativos se reemplazan con len - index .

Si combina estas reglas y notas, tendrá sentido por qué recibió una lista vacía. En tu caso:

In[1]: [1, 2, 3, 4, 5, 6][:-1:-1] # `c` is negative so `a` is -1 and `b` is -1 Out[1]: [] # it is the same as: In[2]: [1, 2, 3, 4, 5, 6][-1: -1: -1] # which will produce you an empty list Out[2]: []

Hay una muy buena discusión acerca de la notación de división : ¡ Explique la notación de división de Python !

Pensé que entendía los conceptos básicos de la división de listas en python, pero he estado recibiendo un error inesperado al usar un paso negativo en una división, de la siguiente manera:

>>> a = list(range(10)) >>> a [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] >>> a[:-1] [0, 1, 2, 3, 4, 5, 6, 7, 8] >>> a[::-1] [9, 8, 7, 6, 5, 4, 3, 2, 1, 0] >>> a[:-1:-1] []

(Tenga en cuenta que esto se está ejecutando en Python 3.5)

¿Por qué un paso [: - 1: -1] a la inversa no recorre el corte a [: - 1] de la misma manera que lo hace a través de toda la lista con un [:: - 1]?

Me doy cuenta de que también puedes usar list.reverse (), pero tratar de comprender mejor la funcionalidad subyacente de la porción python.


Las rodajas de Python parecen bastante simples al principio, pero su comportamiento es bastante complejo (las notas 3 y 5 son relevantes aquí). Si tienes un sector a[i:j:k] :

  • Si i o j son negativos, se refieren a un índice desde el final de a (por lo que a[-1] refiere al último elemento de a )
  • Si i o j no están especificados, o son None , se ubican por defecto en los extremos de a , pero los extremos dependen del signo de k :

    • si k es positivo, estás rebanando hacia delante, por lo que i convierte en 0 y j convierte en len(a)
    • si k es negativo, estás rebanando hacia atrás, por lo que i convierte en len(a) y j convierte en el elemento antes del inicio de a .

      NB: j no puede reemplazarse con -1, ya que al hacerlo, Python tratará a j como el último elemento de a elemento a lugar del elemento (inexistente) antes de a[0] . Para obtener el comportamiento deseado, debe usar -len(a)-1 (o -(len(a)+1) ) en lugar de j , lo que significa que para obtener a[j] , el sector comienza en el último elemento de a , va a la izquierda para los elementos len(a) y luego deja un elemento más, termina antes de a inicio y, por lo tanto, incluye a[0] en la división.

Por lo tanto, a[:-1:-1] significa "ir desde el final de a , que es a[-1] (ya que i no está especificado y k es negativo), hasta el último elemento de a (ya que j == -1 ), con un tamaño de paso de -1 ". i y j son iguales: usted comienza y detiene el corte en el mismo lugar, por lo que la expresión se convierte en una lista vacía.

Para invertir a[:-1] , puede usar a[-2::-1] . De esta manera, la división comienza en el penúltimo elemento, a[-2] (ya que a[:-1] no incluye a[-1] ) y retrocede hasta que el elemento "antes" a[0] , lo que significa que a[0] está incluido en la rebanada.

>>> a [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] >>> a[:-1] [0, 1, 2, 3, 4, 5, 6, 7, 8] >>> a[-2::-1] [8, 7, 6, 5, 4, 3, 2, 1, 0]


Por lo general, me parece útil cortar un objeto de range (esto solo es posible en python3; en el range python2 range produce una list y no se puede dividir el range x) si necesito ver qué índices se usan para una lista de una longitud determinada:

>>> range(10)[::-1] range(9, -1, -1) >>> range(10)[:-1] range(0, 9)

Y en tu último caso:

>>> range(10)[:-1:-1] range(9, 9, -1)

Esto también explica lo que pasó. El primer índice es 9, pero 9 no es más bajo que el índice de parada 9 (tenga en cuenta que en python se excluye el índice de parada), por lo que se detiene sin dar ningún elemento.

Tenga en cuenta que la indexación también se puede aplicar secuencialmente:

>>> list(range(10))[::-1][:-1] # first reverse then exclude last item. [9, 8, 7, 6, 5, 4, 3, 2, 1] >>> list(range(10))[:-1][::-1] # other way around [8, 7, 6, 5, 4, 3, 2, 1, 0]


slice funciona de manera similar al range en el que al hacer que el argumento de step un número negativo, los argumentos de start y stop funcionan en la dirección opuesta.

>>> list(range(9, -1, -1)) == a[::-1] True

Algunos ejemplos que pueden ayudar a aclarar esto:

>>> a[6:2:-2] [6, 4] >>> a[0:None:1] == a[::] True >>> a[-1:None:-1] == a[::-1] True >>> a[-2:None:-1] == a[:-1][::-1] True


El primer -1 en a[:-1:-1] no significa lo que crees que hace.

En el corte, los índices de inicio / fin negativos no se interpretan literalmente. En su lugar, se utilizan para referirse convenientemente al final de la lista (es decir, son relativos a len(a) ). Esto sucede independientemente de la dirección del corte.

Esto significa que

a[:-1:-1]

es equivalente a

a[:len(a)-1:-1]

Cuando se omite durante el corte inverso, el índice de inicio predeterminado es len(a)-1 , haciendo que el equivalente anterior sea

a[len(a)-1:len(a)-1:-1]

Esto siempre da una lista vacía, ya que los índices de inicio y fin son los mismos y el índice de finalización es exclusivo.

Para dividir en reversa hasta, e incluyendo, el elemento cero puede usar cualquiera de las siguientes notaciones:

>>> a[::-1] [9, 8, 7, 6, 5, 4, 3, 2, 1, 0] >>> a[:None:-1] [9, 8, 7, 6, 5, 4, 3, 2, 1, 0] >>> a[:-len(a)-1:-1] [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]