Jeg trenger en god forklaring (referanser er et pluss) på Pythons slice-notasjon.
For meg trenger denne notasjonen litt å plukke opp.
Det ser ekstremt kraftig ut, men jeg har ikke helt fått hodet rundt det.
Det er egentlig ganske enkelt:
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
Det er også step
-verdien, som kan brukes med hvilken som helst av de ovennevnte:
a[start:stop:step] # start through not past stop, by step
Det viktigste å huske er at :stop
-verdien representerer den første verdien som ikke er i det valgte utsnittet. Forskjellen mellom stop
og start
er altså antall elementer som er valgt (hvis step
er 1, som er standard).
Den andre funksjonen er at start
eller stop
kan være et negativt tall, noe som betyr at det teller fra slutten av matrisen i stedet for begynnelsen. Det vil si at man teller fra slutten av arrayet i stedet for begynnelsen:
a[-1] # last item in the array
a[-2:] # last two items in the array
a[:-2] # everything except the last two items
På samme måte kan step
være et negativt tall:
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 er snill mot programmereren hvis det er færre elementer enn du ber om. Hvis du for eksempel ber om a[:-2]
og a
bare inneholder ett element, får du en tom liste i stedet for en feil. Noen ganger foretrekker du feilen, så du må være klar over at dette kan skje.
Relasjon til slice()
-objektet ### Relasjon til slice()
-objektet
Slicing-operatoren []
blir faktisk brukt i koden ovenfor med et slice()
-objekt som bruker :
-notasjonen (som bare er gyldig innenfor []
), dvs:
a[start:stop:step]
er ekvivalent med:
a[slice(start, stop, step)]
Slice-objekter oppfører seg også litt forskjellig avhengig av antall argumenter, på samme måte som range()
, dvs. både slice(stop)
og slice(start, stop[, step])
støttes.
For å hoppe over å spesifisere et gitt argument kan man bruke None
, slik at f.eks. a[start:]
er ekvivalent med a[slice(start, None)]
eller a[::-1]
er ekvivalent med a[slice(None, None, -1)]
.
Selv om den :
-baserte notasjonen er svært nyttig for enkel slicing, forenkler eksplisitt bruk av slice()
-objekter den programmatiske genereringen av slicing.
Python-opplæringen]1 snakker om det (bla litt nedover til du kommer til delen om slicing).
ASCII-kunstdiagrammet er også nyttig for å huske hvordan skiver fungerer:
+---+---+---+---+---+---+
| P | y | t | h | o | n |
+---+---+---+---+---+---+
0 1 2 3 4 5 6
-6 -5 -4 -3 -2 -1
En måte å huske hvordan skiver fungerer på er å tenke på indeksene som pekende mellom tegn, med venstre kant av det første tegnet nummerert 0. Da har høyre kant av det siste tegnet i en streng med n tegn indeks n.
Oppregning av mulighetene som grammatikken tillater:
>>> 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]]
Selvfølgelig, hvis (high-low)%stride != 0
, vil sluttpunktet være litt lavere enn high-1
.
Hvis stride
er negativ, endres rekkefølgen litt siden vi teller ned:
>>> 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]]
Utvidet slicing (med komma og ellipser) brukes for det meste bare av spesielle datastrukturer (som NumPy); de grunnleggende sekvensene støtter dem ikke.
>>> class slicee:
... def __getitem__(self, item):
... return repr(item)
...
>>> slicee()[0, 1:2, ::5, ...]
'(0, slice(1, 2, None), slice(None, None, 5), Ellipsis)'