¿Por qué funciona la división de subcadenas con índice fuera de rango?


88

¿Por qué no da como 'example'[999:9999]resultado un error? Dado 'example'[9]que lo hace, ¿cuál es la motivación detrás de esto?

A partir de este comportamiento, puedo suponer que 'example'[3], esencialmente / internamente, no es lo mismo que 'example'[3:4], aunque ambos dan como resultado la misma 'm'cadena.


17
[999:9999]no es un índice, es un segmento y tiene una semántica diferente. De la introducción de Python: "Los índices de sectores degenerados se manejan con elegancia: un índice que es demasiado grande se reemplaza por el tamaño de la cadena, un límite superior más pequeño que el límite inferior devuelve una cadena vacía".
Wooble

2
@Wooble esa es la respuesta real
jondavidjohn

2
@Wooble ¿Y sabes por qué es así? Gracias por tu aclaración.
ijverig

¿Por qué? Tendrías que preguntarle a Guido, pero creo que es elegante poder asumir que un segmento es siempre el mismo tipo de secuencia que la secuencia original, yo mismo.
Wooble

1
@Lapinot sí, he escrito un código que depende de este comportamiento. Desafortunadamente, no puedo recordar el código exacto, así que no puedo decirte por qué. Probablemente tuvo que ver con subcadenas; obtener una cadena vacía puede ser exactamente lo que desea a veces.
Mark Ransom

Respuestas:


68

¡Estás en lo correcto! 'example'[3:4]y 'example'[3]son fundamentalmente diferentes, y cortar fuera de los límites de una secuencia (al menos para elementos integrados) no causa un error.

Puede resultar sorprendente al principio, pero tiene sentido cuando se piensa en ello. La indexación devuelve un solo elemento, pero la división devuelve una subsecuencia de elementos. Entonces, cuando intentas indexar un valor inexistente, no hay nada que devolver. Pero cuando corta una secuencia fuera de los límites, aún puede devolver una secuencia vacía.

Parte de lo que es confuso aquí es que las cadenas se comportan un poco diferente a las listas. Mira lo que pasa cuando haces lo mismo con una lista:

>>> [0, 1, 2, 3, 4, 5][3]
3
>>> [0, 1, 2, 3, 4, 5][3:4]
[3]

Aquí la diferencia es obvia. En el caso de las cadenas, los resultados parecen ser idénticos porque en Python, no existe un carácter individual fuera de una cadena. Un solo carácter es solo una cadena de 1 carácter.

(Para conocer la semántica exacta de cortar fuera del rango de una secuencia, consulte la respuesta de mgilson ).


1
Un índice fuera de rango podría haber regresado en Nonelugar de generar un error; esa es la convención habitual de Python cuando no tiene nada que devolver.
Mark Ransom

8
@MarkRansom, eso es cierto; pero regresar Noneen este caso haría más difícil distinguir entre un índice fuera de límites y un Nonevalor dentro de una lista. Pero incluso si hubiera una solución para eso, queda claro para mí que devolver una secuencia vacía es lo correcto cuando se le da un segmento fuera de los límites. Es análogo a realizar la unión de dos conjuntos disjuntos.
remitente

Para que quede claro, no dije que estuvieras equivocado. Veo su punto sobre los Nonevalores en una lista.
Mark Ransom

1
@MarkRansom, lo sé, lo siento si soné a la defensiva. Realmente solo quería una excusa para referirme a la teoría de conjuntos :).
remitente

4
Oh, excepto que dije "unión" en lugar de "intersección".
remitente

31

Por el simple hecho de agregar una respuesta que apunte a una sección sólida en la documentación :

Dada una expresión de corte como s[i:j:k],

El segmento de s de i a j con el paso k se define como la secuencia de elementos con índice x = i + n*ktal que 0 <= n < (j-i)/k. En otras palabras, los índices son i, i+k, i+2*k, i+3*ky así sucesivamente, deteniéndose cuando j se alcanza (pero nunca incluyendo j ). Cuando k es positivo, i y j se reducen a len(s)si son mayores

si escribe s[999:9999], Python está regresando s[len(s):len(s)]desde len(s) < 999y su paso es positivo ( 1- el predeterminado).


Presumiblemente, ¿cuándo kes positivo iy jtambién aumenta a -len(s)cuando son menores? por ejemplos = 'bac'; s[-100:2] == s[-len(s):2]
Chris_Rands

@Chris_Rands Cuando ksea ​​positivo, Python escalará iy jse ajustará a los límites de la secuencia. En tu ejemplo, s[-100:2] == s[0:2]( == s[-len(s):2], por cierto). Del mismo modo, s[-100:100] == s[0:2].
tylerc0816

Genial gracias. Esta es una mejor respuesta al comentario anterior de @ speedplane.
remitente

8

Los tipos integrados no comprueban los límites del corte. Y aunque ambos ejemplos parecen tener el mismo resultado, funcionan de manera diferente; pruébelos con una lista.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.