Perché il sezionamento della sottostringa con indice fuori intervallo funziona?


90

Perché non si 'example'[999:9999]verifica un errore? Da allora 'example'[9], qual è la motivazione alla base?

Da questo comportamento posso presumere che 'example'[3]sia, essenzialmente / internamente, non uguale a 'example'[3:4], anche se entrambi risultano nella stessa 'm'stringa.


17
[999:9999]non è un indice, è una sezione e ha una semantica diversa. Dall'introduzione di Python: "Gli indici di slice degeneri vengono gestiti con grazia: un indice troppo grande viene sostituito dalla dimensione della stringa, un limite superiore più piccolo del limite inferiore restituisce una stringa vuota."
Wooble

2
@Wooble questa è la risposta effettiva
jondavidjohn

2
@ Wooble E sai perché è così? Grazie per il tuo chiarimento.
ijverig

Perché? Dovresti chiedere a Guido, ma penso che sia elegante poter presumere che uno slice sia sempre lo stesso tipo di sequenza della sequenza originale, io stesso.
Wooble

1
@ Lapinot sì, ho scritto codice che dipende da questo comportamento. Sfortunatamente non ricordo il codice esatto quindi non posso dirti perché. Probabilmente aveva a che fare con le sottostringhe; ottenere una stringa vuota può essere esattamente quello che vuoi a volte.
Mark Ransom

Risposte:


69

Hai ragione! 'example'[3:4]e 'example'[3]sono fondamentalmente diversi e il taglio al di fuori dei limiti di una sequenza (almeno per i built-in) non causa un errore.

All'inizio potrebbe essere sorprendente, ma ha senso se ci pensi. L'indicizzazione restituisce un singolo elemento, ma il sezionamento restituisce una sottosequenza di elementi. Quindi, quando provi a indicizzare un valore inesistente, non c'è niente da restituire. Ma quando si taglia una sequenza al di fuori dei limiti, è comunque possibile restituire una sequenza vuota.

Parte di ciò che crea confusione qui è che le stringhe si comportano in modo leggermente diverso dalle liste. Guarda cosa succede quando fai la stessa cosa su un elenco:

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

Qui la differenza è evidente. Nel caso delle stringhe, i risultati sembrano essere identici perché in Python non esiste un singolo carattere al di fuori di una stringa. Un singolo carattere è solo una stringa di 1 carattere.

(Per la semantica esatta dell'affettatura al di fuori dell'intervallo di una sequenza, vedere la risposta di mgilson .)


1
Un indice fuori intervallo potrebbe essere restituito Noneinvece di essere errato: questa è la solita convenzione di Python quando non hai nulla da restituire.
Mark Ransom

8
@MarkRansom, è vero; ma il ritorno Nonein questo caso renderebbe più difficile distinguere tra un indice fuori limite e un Nonevalore all'interno di una lista. Ma anche se ci fosse una soluzione alternativa, mi resta chiaro che la restituzione di una sequenza vuota è la cosa giusta da fare quando viene assegnata una porzione fuori limite. È analogo all'esecuzione dell'unione di due insiemi disgiunti.
mittente

Per essere chiari, non ho detto che ti sbagliavi. Vedo la tua opinione sui Nonevalori in un elenco.
Mark Ransom

1
@MarkRansom, lo so - scusa se sembravo sulla difensiva. In realtà volevo solo una scusa per fare riferimento alla teoria degli insiemi :).
mittente

4
Aw, tranne che ho detto "unione" invece di "intersezione".
mittente

33

Per il gusto di aggiungere una risposta che punta a una sezione robusta nella documentazione :

Data un'espressione slice come s[i:j:k],

La fetta di s da i a j con passo k è definita come la sequenza di elementi con indice x = i + n*ktale che 0 <= n < (j-i)/k. In altre parole, gli indici sono i, i+k, i+2*k, i+3*ke così via, fermandosi quando j viene raggiunto (ma mai compreso j ). Quando k è positivo, i e j sono ridotti a len(s)se sono maggiori

se scrivi s[999:9999], python ritorna da s[len(s):len(s)]allora len(s) < 999e il tuo passaggio è positivo ( 1- il valore predefinito).


Presumibilmente quando kè positivo, ie jsono anche aumentati a -len(s)quando sono minori? ad esempios = 'bac'; s[-100:2] == s[-len(s):2]
Chris_Rands

@Chris_Rands Quando kè positivo, Python scalerà ie in jmodo che si adattino ai limiti della sequenza. Nel tuo esempio, s[-100:2] == s[0:2]( == s[-len(s):2], a proposito). Analogamente, s[-100:100] == s[0:2].
tylerc0816

Bene grazie. Questa è una risposta migliore al commento di @ speedplane sopra.
senderle

8

Il sezionamento non è controllato dai limiti dai tipi incorporati. E sebbene entrambi i tuoi esempi sembrino avere lo stesso risultato, funzionano in modo diverso; provali invece con un elenco.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.