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:
- La primera
cestá marcada. El valor predeterminado es+1, el signo decindica la dirección hacia adelante o hacia atrás del paso. El valor absoluto decindica el tamaño del paso. - Que se comprueba una. Cuando
ces positivo oNone, el valor predeterminado paraaes0. Cuandoces negativo, el valor predeterminado paraaes-1. - Finalmente se comprueba
b. Cuandoces positivo oNone, el valor predeterminado parabeslen. Cuandoces negativo, el valor predeterminado parabes-(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
leno0. - 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
cpositivo).
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
iojson negativos, se refieren a un índice desde el final dea(por lo quea[-1]refiere al último elemento dea) Si
iojno están especificados, o sonNone, se ubican por defecto en los extremos dea, pero los extremos dependen del signo dek:- si
kes positivo, estás rebanando hacia delante, por lo queiconvierte en 0 yjconvierte enlen(a) si
kes negativo, estás rebanando hacia atrás, por lo queiconvierte enlen(a)yjconvierte en el elemento antes del inicio dea.NB:
jno puede reemplazarse con -1, ya que al hacerlo, Python tratará ajcomo el último elemento deaelementoalugar del elemento (inexistente) antes dea[0]. Para obtener el comportamiento deseado, debe usar-len(a)-1(o-(len(a)+1)) en lugar dej, lo que significa que para obtenera[j], el sector comienza en el último elemento dea, va a la izquierda para los elementoslen(a)y luego deja un elemento más, termina antes deainicio y, por lo tanto, incluyea[0]en la división.
- si
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]