Risposte:
È piuttosto semplice davvero:
a[start:stop] # items start through stop-1
a[start:] # items start through the rest of the array
a[:stop] # items from the beginning through stop-1
a[:] # a copy of the whole array
C'è anche il step
valore, che può essere utilizzato con uno dei precedenti:
a[start:stop:step] # start through not past stop, by step
Il punto chiave da ricordare è che il :stop
valore rappresenta il primo valore che non si trova nella sezione selezionata. Quindi, la differenza tra stop
e start
è il numero di elementi selezionati (se step
è 1, il valore predefinito).
L'altra caratteristica è che start
o stop
può essere un numero negativo , il che significa che conta dalla fine dell'array anziché dall'inizio. Così:
a[-1] # last item in the array
a[-2:] # last two items in the array
a[:-2] # everything except the last two items
Allo stesso modo, step
può essere un numero negativo:
a[::-1] # all items in the array, reversed
a[1::-1] # the first two items, reversed
a[:-3:-1] # the last two items, reversed
a[-3::-1] # everything except the last two items, reversed
Python è gentile con il programmatore se ci sono meno elementi di quelli richiesti. Ad esempio, se si richiede a[:-2]
e a
contiene solo un elemento, viene visualizzato un elenco vuoto anziché un errore. A volte preferisci l'errore, quindi devi essere consapevole che ciò può accadere.
slice()
oggettoL'operatore slicing []
viene effettivamente utilizzato nel codice sopra con un slice()
oggetto usando la :
notazione (che è valida solo all'interno []
), ovvero:
a[start:stop:step]
è equivalente a:
a[slice(start, stop, step)]
Anche gli oggetti Slice si comportano in modo leggermente diverso a seconda del numero di argomenti, analogamente a range()
entrambi, slice(stop)
e slice(start, stop[, step])
sono supportati. Per saltare la specifica di un determinato argomento, si potrebbe usare None
, in modo che eg a[start:]
sia equivalente a[slice(start, None)]
o a[::-1]
equivalente a[slice(None, None, -1)]
.
Mentre la :
notazione basata su basi è molto utile per lo slicing semplice, l'uso esplicito di slice()
oggetti semplifica la generazione programmatica dello slicing.
None
qualsiasi spazio vuoto. Ad esempio [None:None]
crea un'intera copia. Ciò è utile quando è necessario specificare la fine dell'intervallo utilizzando una variabile e è necessario includere l'ultimo elemento.
del
contiene la notazione slice. In particolare, del arr[:]
non è immediatamente evidente ("arr [:] crea una copia, quindi elimina quella copia ???" ecc.)
Il tutorial di Python ne parla (scorri un po 'verso il basso fino ad arrivare alla parte sull'affettamento).
Il diagramma di arte ASCII è utile anche per ricordare come funzionano le sezioni:
+---+---+---+---+---+---+
| P | y | t | h | o | n |
+---+---+---+---+---+---+
0 1 2 3 4 5 6
-6 -5 -4 -3 -2 -1
Un modo per ricordare come funzionano le sezioni è pensare agli indici come a un punto tra i caratteri, con il bordo sinistro del primo carattere numerato 0. Quindi il bordo destro dell'ultimo carattere di una stringa di n caratteri ha l'indice n .
a[-4,-6,-1]
di esserlo yP
ma lo è ty
. Quello che funziona sempre è pensare nei caratteri o negli slot e usare l'indicizzazione come intervallo semiaperto: apertura a destra se falcata positiva, apertura a sinistra se falcata negativa.
x[:0]
quando si inizia dall'inizio), quindi è necessario creare array di piccole dimensioni per casi speciali. : /
Enumerando le possibilità consentite dalla grammatica:
>>> seq[:] # [seq[0], seq[1], ..., seq[-1] ]
>>> seq[low:] # [seq[low], seq[low+1], ..., seq[-1] ]
>>> seq[:high] # [seq[0], seq[1], ..., seq[high-1]]
>>> seq[low:high] # [seq[low], seq[low+1], ..., seq[high-1]]
>>> seq[::stride] # [seq[0], seq[stride], ..., seq[-1] ]
>>> seq[low::stride] # [seq[low], seq[low+stride], ..., seq[-1] ]
>>> seq[:high:stride] # [seq[0], seq[stride], ..., seq[high-1]]
>>> seq[low:high:stride] # [seq[low], seq[low+stride], ..., seq[high-1]]
Naturalmente, se (high-low)%stride != 0
, il punto finale sarà leggermente inferiore a high-1
.
Se stride
è negativo, l'ordinamento è leggermente cambiato dal momento che stiamo contando:
>>> seq[::-stride] # [seq[-1], seq[-1-stride], ..., seq[0] ]
>>> seq[high::-stride] # [seq[high], seq[high-stride], ..., seq[0] ]
>>> seq[:low:-stride] # [seq[-1], seq[-1-stride], ..., seq[low+1]]
>>> seq[high:low:-stride] # [seq[high], seq[high-stride], ..., seq[low+1]]
Lo slicing esteso (con virgole e puntini di sospensione) viene utilizzato principalmente da strutture dati speciali (come NumPy); le sequenze di base non le supportano.
>>> class slicee:
... def __getitem__(self, item):
... return repr(item)
...
>>> slicee()[0, 1:2, ::5, ...]
'(0, slice(1, 2, None), slice(None, None, 5), Ellipsis)'
repr
__getitem__
è; il tuo esempio è equivalente a apple[slice(4, -4, -1)]
.
Le risposte sopra non parlano dell'assegnazione delle sezioni. Per comprendere l'assegnazione delle sezioni, è utile aggiungere un altro concetto all'arte ASCII:
+---+---+---+---+---+---+
| P | y | t | h | o | n |
+---+---+---+---+---+---+
Slice position: 0 1 2 3 4 5 6
Index position: 0 1 2 3 4 5
>>> p = ['P','y','t','h','o','n']
# Why the two sets of numbers:
# indexing gives items, not lists
>>> p[0]
'P'
>>> p[5]
'n'
# Slicing gives lists
>>> p[0:1]
['P']
>>> p[0:2]
['P','y']
Una euristica è, per una sezione da zero a n, pensare: "zero è l'inizio, iniziare dall'inizio e prendere n elementi in un elenco".
>>> p[5] # the last of six items, indexed from zero
'n'
>>> p[0:5] # does NOT include the last item!
['P','y','t','h','o']
>>> p[0:6] # not p[0:5]!!!
['P','y','t','h','o','n']
Un altro euristico è, "per qualsiasi slice, sostituire l'inizio con zero, applicare l'euristica precedente per ottenere la fine dell'elenco, quindi contare il primo numero di backup per tagliare gli elementi all'inizio"
>>> p[0:4] # Start at the beginning and count out 4 items
['P','y','t','h']
>>> p[1:4] # Take one item off the front
['y','t','h']
>>> p[2:4] # Take two items off the front
['t','h']
# etc.
La prima regola dell'assegnazione delle sezioni è che, poiché la suddivisione restituisce un elenco, l'assegnazione delle sezioni richiede un elenco (o altro iterabile):
>>> p[2:3]
['t']
>>> p[2:3] = ['T']
>>> p
['P','y','T','h','o','n']
>>> p[2:3] = 't'
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: can only assign an iterable
La seconda regola di assegnazione delle sezioni, che puoi anche vedere sopra, è che qualunque parte dell'elenco venga restituita dall'indicizzazione delle sezioni, questa è la stessa porzione che viene modificata dall'assegnazione delle sezioni:
>>> p[2:4]
['T','h']
>>> p[2:4] = ['t','r']
>>> p
['P','y','t','r','o','n']
La terza regola di assegnazione delle sezioni è che l'elenco assegnato (iterabile) non deve avere la stessa lunghezza; la sezione indicizzata viene semplicemente tagliata e sostituita in massa da qualsiasi cosa venga assegnata:
>>> p = ['P','y','t','h','o','n'] # Start over
>>> p[2:4] = ['s','p','a','m']
>>> p
['P','y','s','p','a','m','o','n']
La parte più difficile a cui abituarsi è l'assegnazione a sezioni vuote. Usando l'euristico 1 e 2 è facile orientarsi indicizzando una fetta vuota:
>>> p = ['P','y','t','h','o','n']
>>> p[0:4]
['P','y','t','h']
>>> p[1:4]
['y','t','h']
>>> p[2:4]
['t','h']
>>> p[3:4]
['h']
>>> p[4:4]
[]
E poi, una volta che l'hai visto, ha senso anche l'assegnazione delle sezioni alla sezione vuota:
>>> p = ['P','y','t','h','o','n']
>>> p[2:4] = ['x','y'] # Assigned list is same length as slice
>>> p
['P','y','x','y','o','n'] # Result is same length
>>> p = ['P','y','t','h','o','n']
>>> p[3:4] = ['x','y'] # Assigned list is longer than slice
>>> p
['P','y','t','x','y','o','n'] # The result is longer
>>> p = ['P','y','t','h','o','n']
>>> p[4:4] = ['x','y']
>>> p
['P','y','t','h','x','y','o','n'] # The result is longer still
Si noti che, poiché non stiamo modificando il secondo numero della sezione (4), gli elementi inseriti si impilano sempre esattamente contro la 'o', anche quando stiamo assegnando la sezione vuota. Pertanto, la posizione per l'assegnazione di sezioni vuote è l'estensione logica delle posizioni per le assegnazioni di sezioni non vuote.
Backup un po ', cosa succede quando continui con la nostra processione di contare l'inizio della fetta?
>>> p = ['P','y','t','h','o','n']
>>> p[0:4]
['P','y','t','h']
>>> p[1:4]
['y','t','h']
>>> p[2:4]
['t','h']
>>> p[3:4]
['h']
>>> p[4:4]
[]
>>> p[5:4]
[]
>>> p[6:4]
[]
Con lo slicing, una volta che hai finito, hai finito; non inizia a tagliare all'indietro. In Python non ottieni passi da gigante a meno che tu non li richieda esplicitamente usando un numero negativo.
>>> p[5:3:-1]
['n','o']
Ci sono alcune strane conseguenze sulla regola "una volta che hai finito, hai finito":
>>> p[4:4]
[]
>>> p[5:4]
[]
>>> p[6:4]
[]
>>> p[6]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
IndexError: list index out of range
In effetti, rispetto all'indicizzazione, il slicing di Python è bizzarro a prova di errore:
>>> p[100:200]
[]
>>> p[int(2e99):int(1e99)]
[]
Questo può tornare utile a volte, ma può anche portare a comportamenti piuttosto strani:
>>> p
['P', 'y', 't', 'h', 'o', 'n']
>>> p[int(2e99):int(1e99)] = ['p','o','w','e','r']
>>> p
['P', 'y', 't', 'h', 'o', 'n', 'p', 'o', 'w', 'e', 'r']
A seconda della tua applicazione, questo potrebbe ... o no ... essere quello che speravi lì!
Di seguito è riportato il testo della mia risposta originale. È stato utile a molte persone, quindi non volevo cancellarlo.
>>> r=[1,2,3,4]
>>> r[1:1]
[]
>>> r[1:1]=[9,8]
>>> r
[1, 9, 8, 2, 3, 4]
>>> r[1:1]=['blah']
>>> r
[1, 'blah', 9, 8, 2, 3, 4]
Ciò può anche chiarire la differenza tra suddivisione e indicizzazione.
Spiega la notazione di slice di Python
In breve, i due punti ( :
) in notazione pedice ( subscriptable[subscriptarg]
) make slice notazione - che ha gli argomenti opzionali start
, stop
, step
:
sliceable[start:stop:step]
Python slicing è un modo computazionalmente veloce per accedere metodicamente a parti dei tuoi dati. Secondo me, per essere anche un programmatore Python intermedio, è un aspetto del linguaggio che è necessario conoscere.
Per cominciare, definiamo alcuni termini:
inizio: l'indice iniziale della sezione, includerà l'elemento in questo indice a meno che non sia uguale a stop , il valore predefinito è 0, ovvero il primo indice. Se è negativo, significa iniziare gli
n
oggetti dalla fine.stop: l'indice finale della sezione, non include l'elemento in questo indice, il valore predefinito è la lunghezza della sequenza che viene suddivisa, cioè fino alla fine compresa.
step: la quantità con cui l'indice aumenta, il valore predefinito è 1. Se è negativo, stai tagliando l'iterabile al contrario.
Puoi creare uno di questi numeri positivi o negativi. Il significato dei numeri positivi è semplice, ma per i numeri negativi, proprio come gli indici in Python, conti indietro alla fine per l' inizio e l' arresto , e per il passo semplicemente decrementi l'indice. Questo esempio è tratto dal tutorial della documentazione , ma l'ho leggermente modificato per indicare a quale elemento di una sequenza fa riferimento ciascun indice:
+---+---+---+---+---+---+
| P | y | t | h | o | n |
+---+---+---+---+---+---+
0 1 2 3 4 5
-6 -5 -4 -3 -2 -1
Per usare la notazione di sezioni con una sequenza che la supporta, è necessario includere almeno un punto tra parentesi quadre che seguono la sequenza (che implementa effettivamente il __getitem__
metodo della sequenza, secondo il modello di dati Python ).
La notazione delle sezioni funziona in questo modo:
sequence[start:stop:step]
E ricorda che ci sono impostazioni predefinite per start , stop e step , quindi per accedere alle impostazioni predefinite, lascia semplicemente fuori l'argomento.
Notare la sezione per ottenere gli ultimi nove elementi da un elenco (o qualsiasi altra sequenza che lo supporti, come una stringa) sarebbe simile a questa:
my_list[-9:]
Quando vedo questo, leggo la parte tra parentesi come "9 ° dalla fine alla fine". (In realtà, l'ho abbreviato mentalmente come "-9, on")
La notazione completa è
my_list[-9:None:None]
e per sostituire i valori predefiniti (in realtà quando step
è negativo, stop
il valore predefinito è -len(my_list) - 1
, quindi None
per stop significa solo che va alla fine di qualsiasi passaggio):
my_list[-9:len(my_list):1]
Il colon , :
, è quello che dice Python si sta dando una fetta e non un indice regolare. Ecco perché il modo idiomatico di creare una copia superficiale degli elenchi in Python 2 è
list_copy = sequence[:]
E cancellarli è con:
del my_list[:]
(Python 3 ottiene a list.copy
e list.clear
metodo.)
step
è negativo, l'impostazione predefinita è start
e stop
cambiaPer impostazione predefinita, quando l' step
argomento è vuoto (o None
), viene assegnato a +1
.
Ma puoi passare un numero intero negativo e l'elenco (o la maggior parte degli altri divisibili standard) verrà suddiviso dalla fine all'inizio.
Pertanto una sezione negativa modificherà i valori predefiniti per start
estop
!
Mi piace incoraggiare gli utenti a leggere la fonte e la documentazione. Il codice sorgente per gli oggetti slice e questa logica si trova qui . Innanzitutto determiniamo se step
è negativo:
step_is_negative = step_sign < 0;
In tal caso, il limite inferiore -1
significa che suddividiamo fino all'inizio e includendo l'inizio, e il limite superiore è la lunghezza meno 1, il che significa che iniziamo dalla fine. (Nota che la semantica di questo -1
è diversa da -1
quella in cui gli utenti possono passare indici in Python che indicano l'ultimo elemento.)
if (step_is_negative) { lower = PyLong_FromLong(-1L); if (lower == NULL) goto error; upper = PyNumber_Add(length, lower); if (upper == NULL) goto error; }
Altrimenti step
è positivo e il limite inferiore sarà zero e il limite superiore (a cui andiamo fino ma non includendo) la lunghezza dell'elenco a fette.
else { lower = _PyLong_Zero; Py_INCREF(lower); upper = length; Py_INCREF(upper); }
Quindi, potrebbe essere necessario applicare i valori predefiniti per start
e stop
- il valore predefinito quindi per start
viene calcolato come limite superiore quando step
è negativo:
if (self->start == Py_None) { start = step_is_negative ? upper : lower; Py_INCREF(start); }
e stop
il limite inferiore:
if (self->stop == Py_None) { stop = step_is_negative ? lower : upper; Py_INCREF(stop); }
Potresti trovare utile separare formando la sezione dal passarla al list.__getitem__
metodo ( ecco cosa fanno le parentesi quadre ). Anche se non sei nuovo, mantiene il tuo codice più leggibile in modo che gli altri che potrebbero dover leggere il tuo codice possano capire più facilmente cosa stai facendo.
Tuttavia, non puoi semplicemente assegnare alcuni numeri separati da due punti a una variabile. Devi usare l'oggetto slice:
last_nine_slice = slice(-9, None)
Il secondo argomento, None
è necessario, in modo che il primo argomento sia interpretato come start
argomento, altrimenti sarebbe l' stop
argomento .
È quindi possibile passare l'oggetto slice alla sequenza:
>>> list(range(100))[last_nine_slice]
[91, 92, 93, 94, 95, 96, 97, 98, 99]
È interessante che le gamme prendano anche le sezioni:
>>> range(100)[last_nine_slice]
range(91, 100)
Poiché sezioni di elenchi Python creano nuovi oggetti in memoria, un'altra importante funzione da tenere presente è itertools.islice
. In genere ti consigliamo di scorrere su una porzione, non solo di averla creata staticamente in memoria. islice
è perfetto per questo. Un avvertimento, non supporta argomenti negativi a start
, stop
o step
, quindi, se questo è un problema, potrebbe essere necessario calcolare gli indici o invertire l'iterabile in anticipo.
length = 100
last_nine_iter = itertools.islice(list(range(length)), length-9, None, 1)
list_last_nine = list(last_nine_iter)
e adesso:
>>> list_last_nine
[91, 92, 93, 94, 95, 96, 97, 98, 99]
Il fatto che le sezioni di elenco facciano una copia è una caratteristica delle liste stesse. Se stai tagliando oggetti avanzati come Pandas DataFrame, potrebbe restituire una vista sull'originale e non una copia.
E un paio di cose che non sono state immediatamente ovvie per me quando ho visto per la prima volta la sintassi di taglio:
>>> x = [1,2,3,4,5,6]
>>> x[::-1]
[6,5,4,3,2,1]
Un modo semplice per invertire le sequenze!
E se volessi, per qualche motivo, ogni secondo elemento nella sequenza inversa:
>>> x = [1,2,3,4,5,6]
>>> x[::-2]
[6,4,2]
In Python 2.7
Affettare in Python
[a:b:c]
len = length of string, tuple or list
c -- default is +1. The sign of c indicates forward or backward, absolute value of c indicates steps. Default is forward with step size 1. Positive means forward, negative means backward.
a -- When c is positive or blank, default is 0. When c is negative, default is -1.
b -- When c is positive or blank, default is len. When c is negative, default is -(len+1).
Comprendere l'assegnazione dell'indice è molto importante.
In forward direction, starts at 0 and ends at len-1
In backward direction, starts at -1 and ends at -len
Quando dici [a: b: c], stai dicendo in base al segno di c (avanti o indietro), inizia con a e termina con b (escluso l'elemento all'indice bth). Usa la regola di indicizzazione sopra e ricorda che troverai solo elementi in questo intervallo:
-len, -len+1, -len+2, ..., 0, 1, 2,3,4 , len -1
Ma questa gamma continua in entrambe le direzioni all'infinito:
...,-len -2 ,-len-1,-len, -len+1, -len+2, ..., 0, 1, 2,3,4 , len -1, len, len +1, len+2 , ....
Per esempio:
0 1 2 3 4 5 6 7 8 9 10 11
a s t r i n g
-9 -8 -7 -6 -5 -4 -3 -2 -1
Se la tua scelta di a, b e c consente la sovrapposizione con l'intervallo sopra mentre attraversi usando le regole per a, b, c sopra otterrai una lista con elementi (toccati durante l'attraversamento) o otterrai una lista vuota.
Un'ultima cosa: se aeb sono uguali, allora ottieni anche un elenco vuoto:
>>> l1
[2, 3, 4]
>>> l1[:]
[2, 3, 4]
>>> l1[::-1] # a default is -1 , b default is -(len+1)
[4, 3, 2]
>>> l1[:-4:-1] # a default is -1
[4, 3, 2]
>>> l1[:-3:-1] # a default is -1
[4, 3]
>>> l1[::] # c default is +1, so a default is 0, b default is len
[2, 3, 4]
>>> l1[::-1] # c is -1 , so a default is -1 and b default is -(len+1)
[4, 3, 2]
>>> l1[-100:-200:-1] # Interesting
[]
>>> l1[-1:-200:-1] # Interesting
[4, 3, 2]
>>> l1[-1:-1:1]
[]
>>> l1[-1:5:1] # Interesting
[4]
>>> l1[1:-7:1]
[]
>>> l1[1:-7:-1] # Interesting
[3, 2]
>>> l1[:-2:-2] # a default is -1, stop(b) at -2 , step(c) by 2 in reverse direction
[4]
a = [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ]; a[:-2:-2]
che risulta a[9]
Ho trovato questo fantastico tavolo su http://wiki.python.org/moin/MovingToPythonFromOtherLanguages
Python indexes and slices for a six-element list.
Indexes enumerate the elements, slices enumerate the spaces between the elements.
Index from rear: -6 -5 -4 -3 -2 -1 a=[0,1,2,3,4,5] a[1:]==[1,2,3,4,5]
Index from front: 0 1 2 3 4 5 len(a)==6 a[:5]==[0,1,2,3,4]
+---+---+---+---+---+---+ a[0]==0 a[:-2]==[0,1,2,3]
| a | b | c | d | e | f | a[5]==5 a[1:2]==[1]
+---+---+---+---+---+---+ a[-1]==5 a[1:-1]==[1,2,3,4]
Slice from front: : 1 2 3 4 5 : a[-2]==4
Slice from rear: : -5 -4 -3 -2 -1 :
b=a[:]
b==[0,1,2,3,4,5] (shallow copy of a)
Dopo averlo usato un po 'mi rendo conto che la descrizione più semplice è che è esattamente la stessa degli argomenti in un for
ciclo ...
(from:to:step)
Ognuno di loro è facoltativo:
(:to:step)
(from::step)
(from:to)
Quindi l'indicizzazione negativa deve solo aggiungere la lunghezza della stringa agli indici negativi per capirla.
Questo funziona per me comunque ...
Trovo più facile ricordare come funziona, e quindi riesco a capire qualsiasi combinazione specifica start / stop / step.
È istruttivo capire range()
prima:
def range(start=0, stop, step=1): # Illegal syntax, but that's the effect
i = start
while (i < stop if step > 0 else i > stop):
yield i
i += step
Inizia da start
, incrementa di step
, non raggiungi stop
. Molto semplice.
La cosa da ricordare del passaggio negativo è che stop
è sempre la fine esclusa, sia che sia superiore o inferiore. Se vuoi la stessa fetta nell'ordine opposto, è molto più pulito eseguire l'inversione separatamente: ad esempio, 'abcde'[1:-2][::-1]
taglia un carattere da sinistra, due da destra, quindi inverte. (Vedi anche reversed()
.)
La suddivisione in sequenze è la stessa, tranne per il fatto che prima normalizza gli indici negativi e non può mai uscire dalla sequenza:
TODO : Il codice seguente aveva un bug con "mai andare fuori dalla sequenza" quando abs (step)> 1; Io penso che patchato che sia corretto, ma è difficile da capire.
def this_is_how_slicing_works(seq, start=None, stop=None, step=1):
if start is None:
start = (0 if step > 0 else len(seq)-1)
elif start < 0:
start += len(seq)
if not 0 <= start < len(seq): # clip if still outside bounds
start = (0 if step > 0 else len(seq)-1)
if stop is None:
stop = (len(seq) if step > 0 else -1) # really -1, not last element
elif stop < 0:
stop += len(seq)
for i in range(start, stop, step):
if 0 <= i < len(seq):
yield seq[i]
Non preoccuparti dei is None
dettagli: ricorda che omettere start
e / o fare stop
sempre la cosa giusta per darti l'intera sequenza.
La normalizzazione degli indici negativi consente innanzitutto di contare indipendentemente l'inizio e / o l'arresto dalla fine: 'abcde'[1:-2] == 'abcde'[1:3] == 'bc'
nonostante range(1,-2) == []
. La normalizzazione a volte è pensata come "modulo la lunghezza", ma nota che aggiunge la lunghezza solo una volta: ad esempio 'abcde'[-53:42]
è solo l'intera stringa.
this_is_how_slicing_works
è lo stesso di Python Slice. EG [0, 1, 2][-5:3:3]
otterrà [0] in Python, ma list(this_is_how_slicing_works([0, 1, 2], -5, 3, 3))
otterrà [1].
range(4)[-200:200:3] == [0, 3]
ma list(this_is_how_slicing_works([0, 1, 2, 3], -200, 200, 3)) == [2]
. Il mio if 0 <= i < len(seq):
era un tentativo di implementare "mai andare fuori dalla sequenza" semplicemente ma è sbagliato per il passaggio> 1. Lo riscriverò più tardi oggi (con i test).
Uso il metodo "un indice indica tra gli elementi" per pensarci da solo, ma un modo per descriverlo che a volte aiuta gli altri a ottenerlo è questo:
mylist[X:Y]
X è l'indice del primo elemento desiderato.
Y è l'indice del primo elemento che non vuoi.
Index:
------------>
0 1 2 3 4
+---+---+---+---+---+
| a | b | c | d | e |
+---+---+---+---+---+
0 -4 -3 -2 -1
<------------
Slice:
<---------------|
|--------------->
: 1 2 3 4 :
+---+---+---+---+---+
| a | b | c | d | e |
+---+---+---+---+---+
: -4 -3 -2 -1 :
|--------------->
<---------------|
Spero che questo ti aiuti a modellare l'elenco in Python.
Riferimento: http://wiki.python.org/moin/MovingToPythonFromOtherLanguages
Notazione di slicing Python:
a[start:end:step]
start
e end
, i valori negativi sono interpretati come relativi alla fine della sequenza.end
indicano la posizione dopo l'ultimo elemento da includere.[+0:-0:1]
.start
eend
La notazione si estende a matrici (intorpidite) e matrici multidimensionali. Ad esempio, per tagliare intere colonne è possibile utilizzare:
m[::,0:2:] ## slice the first two columns
Le sezioni contengono riferimenti, non copie, degli elementi dell'array. Se si desidera creare una copia separata di un array, è possibile utilizzare deepcopy()
.
Questo è solo per alcune informazioni extra ... Considera l'elenco qui sotto
>>> l=[12,23,345,456,67,7,945,467]
Pochi altri trucchi per invertire la lista:
>>> l[len(l):-len(l)-1:-1]
[467, 945, 7, 67, 456, 345, 23, 12]
>>> l[:-len(l)-1:-1]
[467, 945, 7, 67, 456, 345, 23, 12]
>>> l[len(l)::-1]
[467, 945, 7, 67, 456, 345, 23, 12]
>>> l[::-1]
[467, 945, 7, 67, 456, 345, 23, 12]
>>> l[-1:-len(l)-1:-1]
[467, 945, 7, 67, 456, 345, 23, 12]
Ecco come insegno le sezioni ai neofiti:
Comprensione della differenza tra indicizzazione e suddivisione:
Wiki Python ha questa fantastica immagine che distingue chiaramente indicizzazione e suddivisione.
È un elenco con sei elementi al suo interno. Per capire meglio l'affettamento, considera tale elenco come un insieme di sei caselle messe insieme. Ogni scatola contiene un alfabeto.
L'indicizzazione è come gestire il contenuto della scatola. Puoi controllare il contenuto di qualsiasi casella. Ma non puoi controllare il contenuto di più caselle contemporaneamente. Puoi persino sostituire il contenuto della confezione. Ma non puoi posizionare due palline in una scatola o sostituire due palline alla volta.
In [122]: alpha = ['a', 'b', 'c', 'd', 'e', 'f']
In [123]: alpha
Out[123]: ['a', 'b', 'c', 'd', 'e', 'f']
In [124]: alpha[0]
Out[124]: 'a'
In [127]: alpha[0] = 'A'
In [128]: alpha
Out[128]: ['A', 'b', 'c', 'd', 'e', 'f']
In [129]: alpha[0,1]
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-129-c7eb16585371> in <module>()
----> 1 alpha[0,1]
TypeError: list indices must be integers, not tuple
Affettare è come gestire le scatole stesse. Puoi prendere la prima scatola e posizionarla su un altro tavolo. Per prendere la scatola, tutto ciò che devi sapere è la posizione di inizio e fine della scatola.
Puoi anche raccogliere le prime tre caselle o le ultime due caselle o tutte le caselle tra 1 e 4. Quindi, puoi scegliere qualsiasi set di caselle se conosci l'inizio e la fine. Queste posizioni sono denominate posizioni iniziale e finale.
La cosa interessante è che puoi sostituire più caselle contemporaneamente. Inoltre puoi posizionare più caselle dove preferisci.
In [130]: alpha[0:1]
Out[130]: ['A']
In [131]: alpha[0:1] = 'a'
In [132]: alpha
Out[132]: ['a', 'b', 'c', 'd', 'e', 'f']
In [133]: alpha[0:2] = ['A', 'B']
In [134]: alpha
Out[134]: ['A', 'B', 'c', 'd', 'e', 'f']
In [135]: alpha[2:2] = ['x', 'xx']
In [136]: alpha
Out[136]: ['A', 'B', 'x', 'xx', 'c', 'd', 'e', 'f']
Affettare con passaggio:
Fino ad ora hai scelto le scatole continuamente. Ma a volte devi raccogliere discretamente. Ad esempio, puoi ritirare ogni seconda casella. Puoi anche ritirare ogni terza scatola dalla fine. Questo valore è chiamato dimensione del gradino. Questo rappresenta il divario tra i tuoi successivi pickup. La dimensione del passo dovrebbe essere positiva se si selezionano caselle dall'inizio alla fine e viceversa.
In [137]: alpha = ['a', 'b', 'c', 'd', 'e', 'f']
In [142]: alpha[1:5:2]
Out[142]: ['b', 'd']
In [143]: alpha[-1:-5:-2]
Out[143]: ['f', 'd']
In [144]: alpha[1:5:-2]
Out[144]: []
In [145]: alpha[-1:-5:2]
Out[145]: []
Come Python calcola i parametri mancanti:
Quando si taglia, se si lascia fuori qualsiasi parametro, Python prova a capirlo automaticamente.
Se controlli il codice sorgente di CPython , troverai una funzione chiamata PySlice_GetIndicesEx () che calcola gli indici in una sezione per ogni dato parametro. Ecco il codice logico equivalente in Python.
Questa funzione accetta un oggetto Python e parametri opzionali per lo slicing e restituisce l'inizio, l'arresto, il passo e la lunghezza dello slice per lo slice richiesto.
def py_slice_get_indices_ex(obj, start=None, stop=None, step=None):
length = len(obj)
if step is None:
step = 1
if step == 0:
raise Exception("Step cannot be zero.")
if start is None:
start = 0 if step > 0 else length - 1
else:
if start < 0:
start += length
if start < 0:
start = 0 if step > 0 else -1
if start >= length:
start = length if step > 0 else length - 1
if stop is None:
stop = length if step > 0 else -1
else:
if stop < 0:
stop += length
if stop < 0:
stop = 0 if step > 0 else -1
if stop >= length:
stop = length if step > 0 else length - 1
if (step < 0 and stop >= start) or (step > 0 and start >= stop):
slice_length = 0
elif step < 0:
slice_length = (stop - start + 1)/(step) + 1
else:
slice_length = (stop - start - 1)/(step) + 1
return (start, stop, step, slice_length)
Questa è l'intelligenza che è presente dietro le sezioni. Poiché Python ha una funzione integrata chiamata slice, è possibile passare alcuni parametri e verificare in che modo calcola i parametri mancanti.
In [21]: alpha = ['a', 'b', 'c', 'd', 'e', 'f']
In [22]: s = slice(None, None, None)
In [23]: s
Out[23]: slice(None, None, None)
In [24]: s.indices(len(alpha))
Out[24]: (0, 6, 1)
In [25]: range(*s.indices(len(alpha)))
Out[25]: [0, 1, 2, 3, 4, 5]
In [26]: s = slice(None, None, -1)
In [27]: range(*s.indices(len(alpha)))
Out[27]: [5, 4, 3, 2, 1, 0]
In [28]: s = slice(None, 3, -1)
In [29]: range(*s.indices(len(alpha)))
Out[29]: [5, 4]
Nota: questo post è stato originariamente scritto nel mio blog, The Intelligence Behind Python Slices .
Come regola generale, la scrittura di codice con molti valori di indice hardcoded porta a problemi di leggibilità e manutenzione. Ad esempio, se torni al codice un anno dopo, lo guarderai e ti chiederai cosa stavi pensando quando lo hai scritto. La soluzione mostrata è semplicemente un modo per affermare più chiaramente cosa sta realmente facendo il tuo codice. In generale, lo slice () incorporato crea un oggetto slice che può essere utilizzato ovunque sia consentita una slice. Per esempio:
>>> items = [0, 1, 2, 3, 4, 5, 6]
>>> a = slice(2, 4)
>>> items[2:4]
[2, 3]
>>> items[a]
[2, 3]
>>> items[a] = [10,11]
>>> items
[0, 1, 10, 11, 4, 5, 6]
>>> del items[a]
>>> items
[0, 1, 4, 5, 6]
Se si dispone di un'istanza di slice, è possibile ottenere ulteriori informazioni su di essa osservando rispettivamente i relativi attributi s.start, s.stop e s.step. Per esempio:
>>> a = slice(10, 50, 2) >>> a.start 10 >>> a.stop 50 >>> a.step 2 >>>
Per semplificare, ricorda che slice ha una sola forma :
s[start:end:step]
ed ecco come funziona:
s
: un oggetto che può essere tagliatostart
: primo indice per avviare l'iterazioneend
: ultimo indice, NOTA che l' end
indice non verrà incluso nella sezione risultantestep
: seleziona l'elemento ogni step
indiceUn'altra cosa di importazione: tutti start
, end
, step
può essere omesso! E se sono omessi, il loro valore di default verrà utilizzato: 0
, len(s)
, 1
di conseguenza.
Quindi le possibili variazioni sono:
# Mostly used variations
s[start:end]
s[start:]
s[:end]
# Step-related variations
s[:end:step]
s[start::step]
s[::step]
# Make a copy
s[:]
NOTA: Se start >= end
(considerando solo quando step>0
), Python restituirà una sezione vuota []
.
La parte precedente spiega le funzionalità principali su come funziona lo slice e funzionerà nella maggior parte dei casi. Tuttavia, ci possono essere insidie da tenere d'occhio e questa parte le spiega.
La prima cosa che confonde gli studenti di Python è che un indice può essere negativo! Niente panico: un indice negativo significa contare all'indietro.
Per esempio:
s[-5:] # Start at the 5th index from the end of array,
# thus returning the last 5 elements.
s[:-5] # Start at index 0, and end until the 5th index from end of array,
# thus returning s[0:len(s)-5].
Rendere le cose più confuse è che step
può essere anche negativo!
Un passaggio negativo significa iterare l'array all'indietro: dalla fine all'inizio, con l'indice di fine incluso e l'indice di inizio escluso dal risultato.
NOTA : quando il passaggio è negativo, il valore predefinito per start
è len(s)
(mentre end
non è uguale a 0
, perché s[::-1]
contiene s[0]
). Per esempio:
s[::-1] # Reversed slice
s[len(s)::-1] # The same as above, reversed slice
s[0:len(s):-1] # Empty list
Sorprendi: lo slice non genera un IndexError quando l'indice è fuori portata!
Se l'indice non è compreso nell'intervallo, Python farà del suo meglio per impostare l'indice su 0
o in len(s)
base alla situazione. Per esempio:
s[:len(s)+5] # The same as s[:len(s)]
s[-len(s)-5::] # The same as s[0:]
s[len(s)+5::-1] # The same as s[len(s)::-1], and the same as s[::-1]
Finiamo questa risposta con esempi, spiegando tutto ciò di cui abbiamo discusso:
# Create our array for demonstration
In [1]: s = [i for i in range(10)]
In [2]: s
Out[2]: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
In [3]: s[2:] # From index 2 to last index
Out[3]: [2, 3, 4, 5, 6, 7, 8, 9]
In [4]: s[:8] # From index 0 up to index 8
Out[4]: [0, 1, 2, 3, 4, 5, 6, 7]
In [5]: s[4:7] # From index 4 (included) up to index 7(excluded)
Out[5]: [4, 5, 6]
In [6]: s[:-2] # Up to second last index (negative index)
Out[6]: [0, 1, 2, 3, 4, 5, 6, 7]
In [7]: s[-2:] # From second last index (negative index)
Out[7]: [8, 9]
In [8]: s[::-1] # From last to first in reverse order (negative step)
Out[8]: [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
In [9]: s[::-2] # All odd numbers in reversed order
Out[9]: [9, 7, 5, 3, 1]
In [11]: s[-2::-2] # All even numbers in reversed order
Out[11]: [8, 6, 4, 2, 0]
In [12]: s[3:15] # End is out of range, and Python will set it to len(s).
Out[12]: [3, 4, 5, 6, 7, 8, 9]
In [14]: s[5:1] # Start > end; return empty list
Out[14]: []
In [15]: s[11] # Access index 11 (greater than len(s)) will raise an IndexError
---------------------------------------------------------------------------
IndexError Traceback (most recent call last)
<ipython-input-15-79ffc22473a3> in <module>()
----> 1 s[11]
IndexError: list index out of range
Le risposte precedenti non trattano la suddivisione in array multidimensionale che è possibile utilizzando il famoso pacchetto NumPy :
L'affettatura può essere applicata anche ad array multidimensionali.
# Here, a is a NumPy array
>>> a
array([[ 1, 2, 3, 4],
[ 5, 6, 7, 8],
[ 9, 10, 11, 12]])
>>> a[:2, 0:3:2]
array([[1, 3],
[5, 7]])
Il " :2
" prima della virgola opera sulla prima dimensione e il " 0:3:2
" dopo la virgola opera sulla seconda dimensione.
list
ma solo su array
Numpy
#!/usr/bin/env python
def slicegraphical(s, lista):
if len(s) > 9:
print """Enter a string of maximum 9 characters,
so the printig would looki nice"""
return 0;
# print " ",
print ' '+'+---' * len(s) +'+'
print ' ',
for letter in s:
print '| {}'.format(letter),
print '|'
print " ",; print '+---' * len(s) +'+'
print " ",
for letter in range(len(s) +1):
print '{} '.format(letter),
print ""
for letter in range(-1*(len(s)), 0):
print ' {}'.format(letter),
print ''
print ''
for triada in lista:
if len(triada) == 3:
if triada[0]==None and triada[1] == None and triada[2] == None:
# 000
print s+'[ : : ]' +' = ', s[triada[0]:triada[1]:triada[2]]
elif triada[0] == None and triada[1] == None and triada[2] != None:
# 001
print s+'[ : :{0:2d} ]'.format(triada[2], '','') +' = ', s[triada[0]:triada[1]:triada[2]]
elif triada[0] == None and triada[1] != None and triada[2] == None:
# 010
print s+'[ :{0:2d} : ]'.format(triada[1]) +' = ', s[triada[0]:triada[1]:triada[2]]
elif triada[0] == None and triada[1] != None and triada[2] != None:
# 011
print s+'[ :{0:2d} :{1:2d} ]'.format(triada[1], triada[2]) +' = ', s[triada[0]:triada[1]:triada[2]]
elif triada[0] != None and triada[1] == None and triada[2] == None:
# 100
print s+'[{0:2d} : : ]'.format(triada[0]) +' = ', s[triada[0]:triada[1]:triada[2]]
elif triada[0] != None and triada[1] == None and triada[2] != None:
# 101
print s+'[{0:2d} : :{1:2d} ]'.format(triada[0], triada[2]) +' = ', s[triada[0]:triada[1]:triada[2]]
elif triada[0] != None and triada[1] != None and triada[2] == None:
# 110
print s+'[{0:2d} :{1:2d} : ]'.format(triada[0], triada[1]) +' = ', s[triada[0]:triada[1]:triada[2]]
elif triada[0] != None and triada[1] != None and triada[2] != None:
# 111
print s+'[{0:2d} :{1:2d} :{2:2d} ]'.format(triada[0], triada[1], triada[2]) +' = ', s[triada[0]:triada[1]:triada[2]]
elif len(triada) == 2:
if triada[0] == None and triada[1] == None:
# 00
print s+'[ : ] ' + ' = ', s[triada[0]:triada[1]]
elif triada[0] == None and triada[1] != None:
# 01
print s+'[ :{0:2d} ] '.format(triada[1]) + ' = ', s[triada[0]:triada[1]]
elif triada[0] != None and triada[1] == None:
# 10
print s+'[{0:2d} : ] '.format(triada[0]) + ' = ', s[triada[0]:triada[1]]
elif triada[0] != None and triada[1] != None:
# 11
print s+'[{0:2d} :{1:2d} ] '.format(triada[0],triada[1]) + ' = ', s[triada[0]:triada[1]]
elif len(triada) == 1:
print s+'[{0:2d} ] '.format(triada[0]) + ' = ', s[triada[0]]
if __name__ == '__main__':
# Change "s" to what ever string you like, make it 9 characters for
# better representation.
s = 'COMPUTERS'
# add to this list different lists to experement with indexes
# to represent ex. s[::], use s[None, None,None], otherwise you get an error
# for s[2:] use s[2:None]
lista = [[4,7],[2,5,2],[-5,1,-1],[4],[-4,-6,-1], [2,-3,1],[2,-3,-1], [None,None,-1],[-5,None],[-5,0,-1],[-5,None,-1],[-1,1,-2]]
slicegraphical(s, lista)
Puoi eseguire questo script e sperimentarlo, di seguito sono riportati alcuni esempi che ho ottenuto dallo script.
+---+---+---+---+---+---+---+---+---+
| C | O | M | P | U | T | E | R | S |
+---+---+---+---+---+---+---+---+---+
0 1 2 3 4 5 6 7 8 9
-9 -8 -7 -6 -5 -4 -3 -2 -1
COMPUTERS[ 4 : 7 ] = UTE
COMPUTERS[ 2 : 5 : 2 ] = MU
COMPUTERS[-5 : 1 :-1 ] = UPM
COMPUTERS[ 4 ] = U
COMPUTERS[-4 :-6 :-1 ] = TU
COMPUTERS[ 2 :-3 : 1 ] = MPUT
COMPUTERS[ 2 :-3 :-1 ] =
COMPUTERS[ : :-1 ] = SRETUPMOC
COMPUTERS[-5 : ] = UTERS
COMPUTERS[-5 : 0 :-1 ] = UPMO
COMPUTERS[-5 : :-1 ] = UPMOC
COMPUTERS[-1 : 1 :-2 ] = SEUM
[Finished in 0.9s]
Quando si utilizza un passaggio negativo, notare che la risposta viene spostata a destra di 1.
Il mio cervello sembra felice di accettare che lst[start:end]
contenga l' start
ennesimo oggetto. Potrei anche dire che si tratta di un "presupposto naturale".
Ma ogni tanto si insinua un dubbio e il mio cervello chiede rassicurazione che non contenga l' end
ennesimo elemento.
In questi momenti mi affido a questo semplice teorema:
for any n, lst = lst[:n] + lst[n:]
Questa bella proprietà mi dice che lst[start:end]
non contiene l' end
elemento -th perché è dentrolst[end:]
.
Nota che questo teorema è vero per n
tutti. Ad esempio, puoi verificarlo
lst = range(10)
lst[:-42] + lst[-42:] == lst
ritorna True
.
Secondo me, capirai e memorizzerai meglio la notazione di suddivisione in stringhe di Python se la guardi nel modo seguente (continua a leggere).
Lavoriamo con la seguente stringa ...
azString = "abcdefghijklmnopqrstuvwxyz"
Per coloro che non lo sanno, è possibile creare qualsiasi sottostringa azString
usando la notazioneazString[x:y]
Proveniente da altri linguaggi di programmazione, è allora che il buon senso viene compromesso. Cosa sono xey?
Ho dovuto sedermi e correre diversi scenari nella mia ricerca di una tecnica di memorizzazione che mi aiuterà a ricordare cosa sono xey e mi aiuterà a tagliare correttamente le stringhe al primo tentativo.
La mia conclusione è che xey dovrebbero essere visti come gli indici di confine che circondano le stringhe che vogliamo aggiungere. Quindi dovremmo vedere l'espressione come azString[index1, index2]
o ancora più chiara come azString[index_of_first_character, index_after_the_last_character]
.
Ecco un esempio di visualizzazione di quello ...
Letters a b c d e f g h i j ...
↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑
┊ ┊
Indexes 0 1 2 3 4 5 6 7 8 9 ...
┊ ┊
cdefgh index1 index2
Quindi tutto ciò che devi fare è impostare index1 e index2 sui valori che circonderanno la sottostringa desiderata. Ad esempio, per ottenere la sottostringa "cdefgh", è possibile utilizzareazString[2:8]
, poiché l'indice sul lato sinistro di "c" è 2 e quello sulla dimensione giusta di "h" è 8.
Ricorda che stiamo definendo i confini. E quei confini sono le posizioni in cui è possibile posizionare alcune parentesi che verranno avvolte attorno alla sottostringa in questo modo ...
ab [ cdefgh ] ij
Quel trucco funziona sempre ed è facile da memorizzare.
La maggior parte delle risposte precedenti chiarisce le domande sulla notazione delle sezioni.
La sintassi di indicizzazione estesa utilizzata per il slicing è aList[start:stop:step]
ed esempi di base sono:
Altri esempi di affettatura: 15 fette estese
In Python, il modulo più semplice per tagliare è il seguente:
l[start:end]
dove l
c'è una raccolta, start
è un indice inclusivo ed end
è un indice esclusivo.
In [1]: l = list(range(10))
In [2]: l[:5] # First five elements
Out[2]: [0, 1, 2, 3, 4]
In [3]: l[-5:] # Last five elements
Out[3]: [5, 6, 7, 8, 9]
Quando si esegue il slicing dall'inizio, è possibile omettere l'indice zero e, se si esegue il slicing fino alla fine, è possibile omettere l'indice finale poiché è ridondante, quindi non essere prolisso:
In [5]: l[:3] == l[0:3]
Out[5]: True
In [6]: l[7:] == l[7:len(l)]
Out[6]: True
Gli interi negativi sono utili quando si eseguono offset relativi alla fine di una raccolta:
In [7]: l[:-1] # Include all elements but the last one
Out[7]: [0, 1, 2, 3, 4, 5, 6, 7, 8]
In [8]: l[-3:] # Take the last three elements
Out[8]: [7, 8, 9]
È possibile fornire indici fuori limite durante il taglio come:
In [9]: l[:20] # 20 is out of index bounds, and l[20] will raise an IndexError exception
Out[9]: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
In [11]: l[-20:] # -20 is out of index bounds, and l[-20] will raise an IndexError exception
Out[11]: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
Tieni presente che il risultato dell'affettatura di una raccolta è una raccolta completamente nuova. Inoltre, quando si utilizza la notazione delle sezioni nelle assegnazioni, la lunghezza delle assegnazioni delle sezioni non deve essere la stessa. I valori prima e dopo la sezione assegnata verranno mantenuti e la raccolta si ridurrà o crescerà per contenere i nuovi valori:
In [16]: l[2:6] = list('abc') # Assigning fewer elements than the ones contained in the sliced collection l[2:6]
In [17]: l
Out[17]: [0, 1, 'a', 'b', 'c', 6, 7, 8, 9]
In [18]: l[2:5] = list('hello') # Assigning more elements than the ones contained in the sliced collection l [2:5]
In [19]: l
Out[19]: [0, 1, 'h', 'e', 'l', 'l', 'o', 6, 7, 8, 9]
Se si omette l'indice di inizio e fine, verrà creata una copia della raccolta:
In [14]: l_copy = l[:]
In [15]: l == l_copy and l is not l_copy
Out[15]: True
Se gli indici di inizio e fine vengono omessi durante l'esecuzione di un'operazione di assegnazione, l'intero contenuto della raccolta verrà sostituito con una copia di ciò a cui viene fatto riferimento:
In [20]: l[:] = list('hello...')
In [21]: l
Out[21]: ['h', 'e', 'l', 'l', 'o', '.', '.', '.']
Oltre all'affettatura di base, è anche possibile applicare la seguente notazione:
l[start:end:step]
dove si l
trova una raccolta, start
è un indice inclusivo, end
è un indice esclusivo ed step
è un passo che può essere utilizzato per includere ogni ennesimo elemento l
.
In [22]: l = list(range(10))
In [23]: l[::2] # Take the elements which indexes are even
Out[23]: [0, 2, 4, 6, 8]
In [24]: l[1::2] # Take the elements which indexes are odd
Out[24]: [1, 3, 5, 7, 9]
L'utilizzo step
fornisce un trucco utile per invertire una raccolta in Python:
In [25]: l[::-1]
Out[25]: [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
È anche possibile utilizzare numeri interi negativi step
come nell'esempio seguente:
In[28]: l[::-2]
Out[28]: [9, 7, 5, 3, 1]
Tuttavia, l'utilizzo di un valore negativo per step
potrebbe diventare molto confuso. Inoltre, al fine di essere Pythonic , si dovrebbe evitare di utilizzare start
, end
e step
in una sola fetta. Nel caso sia necessario, considera di farlo in due compiti (uno da tagliare e l'altro da percorrere).
In [29]: l = l[::2] # This step is for striding
In [30]: l
Out[30]: [0, 2, 4, 6, 8]
In [31]: l = l[1:-1] # This step is for slicing
In [32]: l
Out[32]: [2, 4, 6]
Voglio aggiungerne uno Ciao, Mondo! esempio che spiega le basi delle sezioni per i principianti. Mi ha aiutato molto.
Facciamo un elenco con sei valori ['P', 'Y', 'T', 'H', 'O', 'N']
:
+---+---+---+---+---+---+
| P | Y | T | H | O | N |
+---+---+---+---+---+---+
0 1 2 3 4 5
Ora le sezioni più semplici di tale elenco sono le sue liste secondarie. La notazione è [<index>:<index>]
e la chiave è leggerlo in questo modo:
[ start cutting before this index : end cutting before this index ]
Ora se fai una fetta [2:5]
dell'elenco sopra, questo accadrà:
| |
+---+---|---+---+---|---+
| P | Y | T | H | O | N |
+---+---|---+---+---|---+
0 1 | 2 3 4 | 5
Hai effettuato un taglio prima dell'elemento con indice 2
e un altro taglio prima dell'elemento con indice 5
. Quindi il risultato sarà una fetta tra quei due tagli, un elenco ['T', 'H', 'O']
.
Di seguito è riportato l'esempio di un indice di una stringa:
+---+---+---+---+---+
| H | e | l | p | A |
+---+---+---+---+---+
0 1 2 3 4 5
-5 -4 -3 -2 -1
str="Name string"
Esempio di affettatura: [inizio: fine: passaggio]
str[start:end] # Items start through end-1
str[start:] # Items start through the rest of the array
str[:end] # Items from the beginning through end-1
str[:] # A copy of the whole array
Di seguito è riportato l'uso di esempio:
print str[0] = N
print str[0:2] = Na
print str[0:7] = Name st
print str[0:7:2] = Nm t
print str[0:-1:2] = Nm ti
Se ritieni che gli indici negativi nel taglio siano confusi, ecco un modo molto semplice di pensarci: sostituisci semplicemente l'indice negativo con len - index
. Ad esempio, sostituire -3 con len(list) - 3
.
Il modo migliore per illustrare ciò che lo slicing fa internamente è semplicemente mostrarlo nel codice che implementa questa operazione:
def slice(list, start = None, end = None, step = 1):
# Take care of missing start/end parameters
start = 0 if start is None else start
end = len(list) if end is None else end
# Take care of negative start/end parameters
start = len(list) + start if start < 0 else start
end = len(list) + end if end < 0 else end
# Now just execute a for-loop with start, end and step
return [list[i] for i in range(start, end, step)]
La tecnica di taglio di base consiste nel definire il punto iniziale, il punto di arresto e la dimensione del passo, noto anche come passo.
Innanzitutto, creeremo un elenco di valori da utilizzare nella nostra suddivisione.
Crea due elenchi da tagliare. Il primo è un elenco numerico da 1 a 9 (Elenco A). Il secondo è anche un elenco numerico, da 0 a 9 (Elenco B):
A = list(range(1, 10, 1)) # Start, stop, and step
B = list(range(9))
print("This is List A:", A)
print("This is List B:", B)
Indicizza il numero 3 da A e il numero 6 da B.
print(A[2])
print(B[6])
Affettatura di base
La sintassi di indicizzazione estesa utilizzata per lo slicing è aList [start: stop: step]. L'argomento start e l'argomento step sono entrambi predefiniti su none - l'unico argomento richiesto è stop. Hai notato che è simile a come è stato utilizzato l'intervallo per definire gli elenchi A e B? Questo perché l'oggetto slice rappresenta l'insieme di indici specificato dall'intervallo (start, stop, step). Documentazione di Python 3.4.
Come puoi vedere, la definizione di solo stop restituisce un elemento. Poiché l'avvio non è impostato su nessuno, questo si traduce nel recupero di un solo elemento.
È importante notare che il primo elemento è l'indice 0, non indice 1. Questo è il motivo per cui stiamo usando 2 elenchi per questo esercizio. Gli elementi dell'elenco A sono numerati in base alla posizione ordinale (il primo elemento è 1, il secondo elemento è 2, ecc.) Mentre gli elementi dell'elenco B sono i numeri che verrebbero utilizzati per indicizzarli ([0] per il primo elemento 0, eccetera.).
Con una sintassi di indicizzazione estesa, recuperiamo un intervallo di valori. Ad esempio, tutti i valori vengono recuperati con due punti.
A[:]
Per recuperare un sottoinsieme di elementi, è necessario definire le posizioni iniziale e finale.
Dato il modello aList [start: stop], recupera i primi due elementi dall'elenco A.
Non penso che il diagramma tutorial di Python (citato in varie altre risposte) sia buono in quanto questo suggerimento funziona per il passo positivo, ma non per un passo negativo.
Questo è il diagramma:
+---+---+---+---+---+---+
| P | y | t | h | o | n |
+---+---+---+---+---+---+
0 1 2 3 4 5 6
-6 -5 -4 -3 -2 -1
Dal diagramma, mi aspetto a[-4,-6,-1]
di esserlo yP
ma lo è ty
.
>>> a = "Python"
>>> a[2:4:1] # as expected
'th'
>>> a[-4:-6:-1] # off by 1
'ty'
Quello che funziona sempre è pensare nei caratteri o negli slot e usare l'indicizzazione come intervallo semiaperto: apertura a destra se falcata positiva, apertura a sinistra se falcata negativa.
In questo modo, posso pensare a a[-4:-6:-1]
come a(-6,-4]
nella terminologia intervallo.
+---+---+---+---+---+---+
| P | y | t | h | o | n |
+---+---+---+---+---+---+
0 1 2 3 4 5
-6 -5 -4 -3 -2 -1
+---+---+---+---+---+---+---+---+---+---+---+---+
| P | y | t | h | o | n | P | y | t | h | o | n |
+---+---+---+---+---+---+---+---+---+---+---+---+
-6 -5 -4 -3 -2 -1 0 1 2 3 4 5