Plaknotatie begrijpen

Ik heb een goede uitleg nodig (referenties zijn een pluspunt) over de slice-notatie van Python.

Voor mij moet deze notatie wat opgepikt worden.

Het ziet er extreem krachtig uit, maar ik heb er mijn hoofd niet bij.


Antwoord 1, autoriteit 100%

Het is eigenlijk vrij eenvoudig:

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

Er is ook de waarde step, die kan worden gebruikt met elk van de bovenstaande:

a[start:stop:step] # start through not past stop, by step

Het belangrijkste om te onthouden is dat de waarde :stop de eerste waarde vertegenwoordigt die niet is in het geselecteerde segment. Het verschil tussen stop en start is dus het aantal geselecteerde elementen (als step 1 is, is dit de standaardinstelling).

Het andere kenmerk is dat start of stop een negatief getal kan zijn, wat betekent dat het vanaf het einde van de array telt in plaats van het begin. Dus:

a[-1]    # last item in the array
a[-2:]   # last two items in the array
a[:-2]   # everything except the last two items

Evenzo kan step een negatief getal zijn:

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 is vriendelijk voor de programmeur als er minder items zijn dan je vraagt. Als je bijvoorbeeld om a[:-2] vraagt ​​en a maar één element bevat, krijg je een lege lijst in plaats van een foutmelding. Soms geeft u de voorkeur aan de fout, dus u moet zich ervan bewust zijn dat dit kan gebeuren.

Relatie met slice() object

De slicing-operator [] wordt feitelijk gebruikt in de bovenstaande code met een slice()-object met de notatie : (wat alleen geldig binnen []), dwz:

a[start:stop:step]

is gelijk aan:

a[slice(start, stop, step)]

Slice-objecten gedragen zich ook iets anders, afhankelijk van het aantal argumenten, vergelijkbaar met range(), dwz zowel slice(stop) als slice(start, stop[, step]) worden ondersteund.
Om het specificeren van een gegeven argument over te slaan, zou men None kunnen gebruiken, zodat b.v. a[start:] is gelijk aan a[slice(start, None)] of a[::-1] is gelijk aan a[slice(None, None, -1)].

Hoewel de op : gebaseerde notatie erg handig is voor eenvoudig slicen, vereenvoudigt het expliciete gebruik van slice()-objecten het programmatisch genereren van slicen.


Antwoord 2, autoriteit 11%

De Python-tutorial vertelt erover (scroll een beetje naar beneden totdat je naar het gedeelte over snijden).

Het ASCII-kunstdiagram is ook handig om te onthouden hoe slices werken:

 +---+---+---+---+---+---+
 | P | y | t | h | o | n |
 +---+---+---+---+---+---+
 0   1   2   3   4   5   6
-6  -5  -4  -3  -2  -1

Een manier om te onthouden hoe slices werken, is door de indices te zien als tussen tekens, waarbij de linkerrand van het eerste teken het nummer 0 heeft. Dan de rechterrand van het laatste teken van een tekenreeks van n tekens heeft index n.


Antwoord 3, autoriteit 8%

Opsomming van de mogelijkheden die de grammatica toelaat:

>>> 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]]

Natuurlijk, als (high-low)%stride != 0, dan zal het eindpunt iets lager zijn dan high-1.

Als stride negatief is, is de volgorde een beetje veranderd omdat we aan het aftellen zijn:

>>> 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]]

Extended slicing (met komma’s en ellipsen) wordt meestal alleen gebruikt door speciale datastructuren (zoals NumPy); de basisreeksen ondersteunen ze niet.

>>> class slicee:
...     def __getitem__(self, item):
...         return repr(item)
...
>>> slicee()[0, 1:2, ::5, ...]
'(0, slice(1, 2, None), slice(None, None, 5), Ellipsis)'

Antwoord 4, autoriteit 7%

De bovenstaande antwoorden gaan niet over segmenttoewijzing. Om de slice-toewijzing te begrijpen, is het handig om een ​​ander concept aan de ASCII-art toe te voegen:

                +---+---+---+---+---+---+
                | 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']

Eén heuristiek is, voor een segment van nul tot n, denk: “nul is het begin, begin bij het begin en neem n items in een lijst”.

>>> 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']

Een andere heuristiek is: “vervang voor elk segment het begin door nul, pas de vorige heuristiek toe om het einde van de lijst te krijgen en tel vervolgens het eerste getal weer op om items van het begin af te hakken”

>>> 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.

De eerste regel van slice-toewijzing is dat aangezien slicen een lijst retourneert, slice-toewijzing vereist een lijst (of andere itereerbare):

>>> 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

De tweede regel van segmenttoewijzing, die u ook hierboven kunt zien, is dat welk deel van de lijst ook wordt geretourneerd door segmentindexering, dat hetzelfde deel is dat wordt gewijzigd door segmenttoewijzing:

>>> p[2:4]
 ['T','h']
>>> p[2:4] = ['t','r']
>>> p
 ['P','y','t','r','o','n']

De derde regel van slice-toewijzing is dat de toegewezen lijst (itereerbaar) niet dezelfde lengte hoeft te hebben; het geïndexeerde segment wordt eenvoudigweg uitgesneden en massaal vervangen door wat er ook wordt toegewezen:

>>> 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']

Het lastigste om aan te wennen is de toewijzing aan lege segmenten. Met behulp van heuristiek 1 en 2 is het gemakkelijk om een ​​leeg segment te indexeren:

>>> 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]
 []

En als je dat eenmaal hebt gezien, is het toewijzen van slices aan de lege slice ook logisch:

>>> 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

Merk op dat, aangezien we het tweede nummer van het segment (4) niet veranderen, de ingevoegde items altijd recht tegen de ‘o’ aan liggen, zelfs wanneer we het toewijzen aan het lege segment. De positie voor de lege slice-toewijzing is dus het logische verlengstuk van de posities voor de niet-lege slice-toewijzingen.

Een beetje achteruitgaan, wat gebeurt er als je doorgaat met onze processie van het optellen van het plakje?

>>> 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]
 []

Als je klaar bent met snijden, ben je klaar; het begint niet achteruit te snijden. In Python krijg je geen negatieve stappen tenzij je er expliciet om vraagt ​​door een negatief getal te gebruiken.

>>> p[5:3:-1]
 ['n','o']

Er zijn enkele rare gevolgen aan de regel “als je klaar bent, ben je klaar”:

>>> 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 vergelijking met indexeren is Python-slicing zelfs bizar foutbestendig:

>>> p[100:200]
 []
>>> p[int(2e99):int(1e99)]
 []

Dit kan soms van pas komen, maar het kan ook leiden tot enigszins vreemd gedrag:

>>> 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']

Afhankelijk van uw toepassing, is dat misschien… of misschien niet… waar u op hoopte!


Hieronder staat de tekst van mijn oorspronkelijke antwoord. Het is voor veel mensen nuttig geweest, dus ik wilde het niet verwijderen.

>>> 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]

Dit kan ook het verschil tussen slicen en indexeren verduidelijken.


Antwoord 5, autoriteit 5%

Leg de slice-notatie van Python uit

Kortom, de dubbele punten (:) in subscriptnotatie (subscriptable[subscriptarg]) maken slice-notatie – die de optionele argumenten heeft, start, stop, step:

sliceable[start:stop:step]

Python-slicing is een rekenkundig snelle manier om methodisch toegang te krijgen tot delen van uw gegevens. Naar mijn mening, om zelfs maar een gemiddelde Python-programmeur te zijn, is het een aspect van de taal waarmee je bekend moet zijn.

Belangrijke definities

Laten we om te beginnen een paar termen definiëren:

start: de beginindex van het segment, het bevat het element in deze index tenzij het hetzelfde is als stop, standaard ingesteld op 0, dwz de eerste index . Als het negatief is, betekent dit dat u n items vanaf het einde moet beginnen.

stop: de eindindex van het segment, het bevat niet het element bij deze index, standaard ingesteld op de lengte van de reeks die wordt gesneden, dat wil zeggen tot en inclusief het einde.

stap: het bedrag waarmee de index toeneemt, is standaard 1. Als het negatief is, snijdt u de iterabele in omgekeerde volgorde door.

Hoe indexeren werkt

U kunt elk van deze positieve of negatieve getallen maken. De betekenis van de positieve getallen is eenvoudig, maar voor negatieve getallen, net als indexen in Python, tel je terug vanaf het einde voor de start en stop, en voor de step, verlaagt u eenvoudig uw index. Dit voorbeeld is uit de handleiding van de documentatie, maar ik heb het enigszins aangepast om aan te geven naar welk item in een reeks elke index verwijst:

 +---+---+---+---+---+---+
 | P | y | t | h | o | n |
 +---+---+---+---+---+---+
   0   1   2   3   4   5 
  -6  -5  -4  -3  -2  -1

Hoe snijden werkt

Als u segmentnotatie wilt gebruiken met een reeks die dit ondersteunt, moet u ten minste één dubbele punt opnemen tussen de vierkante haken die volgen op de reeks (die in feite implementeer de __getitem__ methode van de reeks, volgens het Python-gegevensmodel.)

Plaknotatie werkt als volgt:

sequence[start:stop:step]

En onthoud dat er standaardwaarden zijn voor start, stop en step, dus om toegang te krijgen tot de standaardwaarden, laat u het argument gewoon weg.

Snijdnotatie om de laatste negen elementen uit een lijst te halen (of een andere reeks die dit ondersteunt, zoals een string) ziet er als volgt uit:

my_list[-9:]

Als ik dit zie, lees ik het deel tussen haakjes als "9e vanaf het einde, tot het einde." (Eigenlijk kort ik het mentaal af als "-9, aan")

Uitleg:

De volledige notatie is

my_list[-9:None:None]

en om de standaardwaarden te vervangen (eigenlijk wanneer step negatief is, is de standaardinstelling van stop -len(my_list) - 1, dus None voor stoppen betekent eigenlijk gewoon dat het naar de eindstap gaat waar het naartoe gaat):

my_list[-9:len(my_list):1]

De dubbele punt, :, is wat Python vertelt dat je het een segment geeft en geen reguliere index. Daarom is de idiomatische manier om een ​​oppervlakkige kopie van lijsten te maken in Python 2

list_copy = sequence[:]

En het wissen ervan is met:

del my_list[:]

(Python 3 krijgt een list.copy en list.clear methode.)

Als step negatief is, veranderen de standaardwaarden voor start en stop

Als het argument step leeg is (of None), wordt het standaard toegewezen aan +1.

Maar u kunt een negatief geheel getal doorgeven, en de lijst (of de meeste andere standaard slicables) wordt van het einde naar het begin gesegmenteerd.

Dus een negatief segment verandert de standaardwaarden voor start en stop!

Dit bevestigen in de bron

Ik moedig gebruikers aan om zowel de bron als de documentatie te lezen. De broncode voor slice-objecten en deze logica is hier te vinden. Eerst bepalen we of step negatief is:

 step_is_negative = step_sign < 0;

Als dat zo is, is de ondergrens -1, wat betekent dat we helemaal doorsnijden tot en met het begin, en de bovengrens is de lengte min 1, wat betekent dat we aan het einde beginnen. (Merk op dat de semantiek van deze -1 anders is dan een -1 dat gebruikers indexen in Python kunnen doorgeven die het laatste item aangeven.)

if (step_is_negative) {
    lower = PyLong_FromLong(-1L);
    if (lower == NULL)
        goto error;
    upper = PyNumber_Add(length, lower);
    if (upper == NULL)
        goto error;
}

Anders is step positief, en de ondergrens is nul en de bovengrens (waartoe we gaan, maar niet meegerekend) de lengte van de gesegmenteerde lijst.

else {
    lower = _PyLong_Zero;
    Py_INCREF(lower);
    upper = length;
    Py_INCREF(upper);
}

Vervolgens moeten we mogelijk de standaardwaarden toepassen voor start en stop – de standaardwaarde voor start wordt berekend als de bovengrens wanneer step is negatief:

if (self->start == Py_None) {
    start = step_is_negative ? upper : lower;
    Py_INCREF(start);
}

en stop, de ondergrens:

if (self->stop == Py_None) {
    stop = step_is_negative ? lower : upper;
    Py_INCREF(stop);
}

Geef je plakjes een beschrijvende naam!

Misschien vindt u het handig om het vormen van het segment te scheiden van het doorgeven ervan aan de list.__getitem__-methode (dat is wat de vierkante haken doen). Zelfs als het niet nieuw voor u is, blijft uw code leesbaarder, zodat anderen die uw code moeten lezen, gemakkelijker kunnen begrijpen wat u doet.

Je kunt echter niet zomaar een aantal gehele getallen, gescheiden door dubbele punten, aan een variabele toewijzen. U moet het slice-object gebruiken:

last_nine_slice = slice(-9, None)

Het tweede argument, None, is vereist, zodat het eerste argument wordt geïnterpreteerd als het start-argument anders zou het het stop-argument zijn.

U kunt het slice-object dan doorgeven aan uw reeks:

>>> list(range(100))[last_nine_slice]
[91, 92, 93, 94, 95, 96, 97, 98, 99]

Het is interessant dat reeksen ook segmenten bevatten:

>>> range(100)[last_nine_slice]
range(91, 100)

Overwegingen bij het geheugen:

Aangezien segmenten van Python-lijsten nieuwe objecten in het geheugen creëren, is itertools.islice een andere belangrijke functie om op te letten. Meestal wilt u een segment herhalen, niet alleen statisch in het geheugen laten maken. islice is hier perfect voor. Een waarschuwing: het ondersteunt geen negatieve argumenten voor start, stop of step, dus als dat een probleem is, moet u mogelijk indices berekenen of keer de iterable van tevoren om.

length = 100
last_nine_iter = itertools.islice(list(range(length)), length-9, None, 1)
list_last_nine = list(last_nine_iter)

en nu:

>>> list_last_nine
[91, 92, 93, 94, 95, 96, 97, 98, 99]

Het feit dat lijstsegmenten een kopie maken, is een kenmerk van lijsten zelf. Als u geavanceerde objecten zoals een Pandas DataFrame in segmenten snijdt, kan het een weergave van het origineel opleveren en geen kopie.


Antwoord 6, autoriteit 3%

En een paar dingen die niet meteen duidelijk voor me waren toen ik de syntaxis voor het snijden voor het eerst zag:

>>> x = [1,2,3,4,5,6]
>>> x[::-1]
[6,5,4,3,2,1]

Eenvoudige manier om reeksen om te draaien!

En als je om de een of andere reden elk tweede item in de omgekeerde volgorde wilt:

>>> x = [1,2,3,4,5,6]
>>> x[::-2]
[6,4,2]

Antwoord 7, autoriteit 2%

In Python 2.7

Snijden 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).

Inzicht in indextoewijzing is erg belangrijk.

In forward direction, starts at 0 and ends at len-1
In backward direction, starts at -1 and ends at -len

Als je [a:b:c] zegt, zeg je, afhankelijk van het teken van c (vooruit of achteruit), begin bij a en eindig bij b (exclusief element bij bth index). Gebruik de bovenstaande indexeringsregel en onthoud dat u alleen elementen in dit bereik zult vinden:

-len, -len+1, -len+2, ..., 0, 1, 2,3,4 , len -1

Maar dit bereik gaat oneindig door in beide richtingen:

...,-len -2 ,-len-1,-len, -len+1, -len+2, ..., 0, 1, 2,3,4 , len -1, len, len +1, len+2 , ....

Bijvoorbeeld:

             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

Als je keuze voor a, b en c overlap toestaat met het bereik hierboven terwijl je de regels voor a,b,c hierboven gebruikt, krijg je ofwel een lijst met elementen (aangeraakt tijdens het doorlopen) of je krijgt een lege lijst.

Nog een laatste ding: als a en b gelijk zijn, dan krijg je ook een lege lijst:

>>> 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]

Antwoord 8, autoriteit 2%

Deze geweldige tabel gevonden op 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)

Antwoord 9

Na het een beetje te hebben gebruikt, realiseer ik me dat de eenvoudigste beschrijving is dat het precies hetzelfde is als de argumenten in een for-lus…

(from:to:step)

Al deze zijn optioneel:

(:to:step)
(from::step)
(from:to)

Dan hoeft u voor de negatieve indexering alleen de lengte van de tekenreeks aan de negatieve indices toe te voegen om deze te begrijpen.

Dit werkt toch voor mij…


Antwoord 10

Ik vind het gemakkelijker om te onthouden hoe het werkt, en dan kan ik een specifieke start/stop/stap-combinatie bedenken.

Het is leerzaam om eerst range() te begrijpen:

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

Begin vanaf start, verhoog met step, bereik stop niet. Heel eenvoudig.

Het ding om te onthouden over negatieve stap is dat stop altijd het uitgesloten einde is, of het nu hoger of lager is. Als u dezelfde plak in tegengestelde volgorde wilt, is het veel schoner om de omkering afzonderlijk te doen: b.v. 'abcde'[1:-2][::-1] snijdt één teken van links af, twee van rechts, en keert dan om. (Zie ook reversed().)

Sequence slicing is hetzelfde, behalve dat het eerst negatieve indexen normaliseert, en het kan nooit buiten de sequentie gaan:

TODO: de onderstaande code had een fout met “ga nooit buiten de reeks” wanneer abs(step)>1; Ik denk dat ik het heb gepatcht om correct te zijn, maar het is moeilijk te begrijpen.

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]

Maak je geen zorgen over de details van is None – onthoud dat het weglaten van start en/of stop altijd het juiste is om te geven jij de hele reeks.

Door eerst negatieve indexen te normaliseren, kunnen start en/of stop onafhankelijk vanaf het einde worden geteld: 'abcde'[1:-2] == 'abcde'[1:3] == 'bc' ondanks range(1,-2) == [].
De normalisatie wordt soms gezien als “modulo de lengte”, maar merk op dat de lengte slechts één keer wordt toegevoegd: b.v. 'abcde'[-53:42] is gewoon de hele string.


Antwoord 11

Ik gebruik de “an index points between elements”-methode om er zelf over na te denken, maar een manier om het te beschrijven die anderen soms helpt om het te begrijpen, is dit:

mylist[X:Y]

X is de index van het eerste element dat u wilt.
Y is de index van het eerste element dat u niet wilt.


Antwoord 12

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   :
|--------------->
    <---------------|

Ik hoop dat dit je zal helpen om de lijst in Python te modelleren.

Referentie: http://wiki.python.org/moin/MovingToPythonFromOtherLanguages


Antwoord 13

Python-slicing-notatie:

a[start:end:step]
  • Voor start en end worden negatieve waarden geïnterpreteerd als relatief ten opzichte van het einde van de reeks.
  • Positieve indices voor end geven de positie aan na het laatste element dat moet worden opgenomen.
  • Lege waarden zijn standaard als volgt: [+0:-0:1].
  • Het gebruik van een negatieve stap keert de interpretatie van start en end
  • om

De notatie strekt zich uit tot (numpy) matrices en multidimensionale arrays. Als u bijvoorbeeld hele kolommen wilt segmenteren, kunt u het volgende gebruiken:

m[::,0:2:] ## slice the first two columns

Slices bevatten verwijzingen, geen kopieën, van de array-elementen. Als je een aparte kopie van een array wilt maken, kun je deepcopy().


Antwoord 14

Zo leer ik nieuwelingen plakjes:

Het verschil tussen indexeren en segmenteren begrijpen:

Wiki Python heeft deze verbazingwekkende afbeelding die duidelijk onderscheid maakt tussen indexeren en segmenteren.

Voer hier de afbeeldingsbeschrijving in

Het is een lijst met zes elementen erin. Om het snijden beter te begrijpen, kunt u die lijst beschouwen als een set van zes dozen die bij elkaar zijn geplaatst. Elke doos heeft een alfabet.

Indexeren is als omgaan met de inhoud van een doos. U kunt de inhoud van elke doos controleren. Maar u kunt niet de inhoud van meerdere dozen tegelijk controleren. U kunt zelfs de inhoud van de doos vervangen. Maar je kunt niet twee ballen in één doos plaatsen of twee ballen tegelijk vervangen.

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

Snijden is als het omgaan met dozen zelf. Je kunt de eerste doos oppakken en op een andere tafel plaatsen. Om de doos op te halen, hoef je alleen maar de positie van het begin en einde van de doos te weten.

Je kunt zelfs de eerste drie dozen of de laatste twee dozen of alle dozen tussen 1 en 4 pakken. Je kunt dus elke reeks dozen kiezen als je het begin en einde weet. Deze posities worden start- en stopposities genoemd.

Het interessante is dat je meerdere vakken tegelijk kunt vervangen. Je kunt ook meerdere dozen plaatsen waar je maar wilt.

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']

Snijden met stap:

Tot nu toe heb je continu dozen gepickt. Maar soms moet je discreet oppakken. U kunt bijvoorbeeld elke tweede doos ophalen. Je kunt zelfs elke derde doos vanaf het einde ophalen. Deze waarde wordt stapgrootte genoemd. Dit vertegenwoordigt de kloof tussen uw opeenvolgende pickups. De stapgrootte moet positief zijn als u dozen van het begin tot het einde kiest en vice versa.

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]: []

Hoe Python de ontbrekende parameters ontdekt:

Als je tijdens het slicen een parameter weglaat, probeert Python deze automatisch te achterhalen.

Als u de broncode van CPython controleert, vindt u een functie genaamd PySlice_GetIndicesEx( ) die indices voor een segment uitrekent voor een bepaalde parameter. Hier is de logische equivalente code in Python.

Deze functie neemt een Python-object en optionele parameters voor slicen en retourneert de start, stop, step en slice-lengte voor de gevraagde slice.

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)

Dit is de intelligentie die achter slices zit. Omdat Python een ingebouwde functie heeft die slice wordt genoemd, kun je een aantal parameters doorgeven en controleren hoe slim het ontbrekende parameters berekent.

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]

Opmerking: dit bericht is oorspronkelijk geschreven in mijn blog, De intelligentie achter Python Slices.


Antwoord 15

U kunt segmenttoewijzing ook gebruiken om een ​​of meer elementen uit een lijst te verwijderen:

r = [1, 'blah', 9, 8, 2, 3, 4]
>>> r[1:4] = []
>>> r
[1, 2, 3, 4]

Antwoord 16

Dit is alleen voor wat extra info…
Bekijk de onderstaande lijst

>>> l=[12,23,345,456,67,7,945,467]

Enkele andere trucs om de lijst om te draaien:

>>> 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]

Antwoord 17

Als algemene regel leidt het schrijven van code met veel hardgecodeerde indexwaarden tot leesbaarheid
en onderhoud puinhoop. Als u bijvoorbeeld een jaar later op de code terugkomt, zult u
kijk ernaar en vraag je af wat je dacht toen je het schreef. De getoonde oplossing
is gewoon een manier om duidelijker aan te geven wat uw code feitelijk doet.
Over het algemeen maakt de ingebouwde slice() een slice-object dat overal in een slice kan worden gebruikt
is toegestaan. Bijvoorbeeld:

>>> 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]

Als je een slice-instantie s hebt, kun je er meer informatie over krijgen door te kijken naar de
respectievelijk s.start, s.stop en s.step attributen. Bijvoorbeeld:

>>> a = slice(10, 50, 2)
>>> a.start
10
>>> a.stop
50
>>> a.step
2
>>>

Antwoord 18

1. Segmentnotatie

Om het simpel te houden, onthoud dat slice maar één vorm heeft:

s[start:end:step]

en zo werkt het:

  • s: een object dat kan worden gesegmenteerd
  • start: eerste index om iteratie te starten
  • end: laatste index, LET OP dat de end index niet zal worden opgenomen in het resulterende segment
  • step: kies element elke step index

Nog iets belangrijks: alle start,end, step kunnen worden weggelaten! En als ze worden weggelaten , wordt hun standaardwaarde gebruikt: 0,len(s),1 dienovereenkomstig.

Dus mogelijke variaties zijn:

# 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[:]

OPMERKING: Als start >= end (alleen rekening houdend met step>0), zal Python een leeg segment [] retourneren.

2. Valkuilen

In het bovenstaande deel worden de kernfuncties uitgelegd over hoe slice werkt, en dit zal bij de meeste gelegenheden ook werken. Er kunnen echter valkuilen zijn waar u op moet letten, en dit deel legt ze uit.

Negatieve indexen

Het allereerste dat Python-leerders in de war brengt, is dat een index negatief kan zijn!
Geen paniek: een negatieve index betekent terugtellen.

Bijvoorbeeld:

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].

Negatieve stap

Om het nog verwarrender te maken, is dat step ook negatief kan zijn!

Een negatieve stap betekent dat de array achteruit moet worden herhaald: van het einde tot het begin, met de eindindex inbegrepen en de startindex uitgesloten van het resultaat.

OPMERKING: wanneer stap negatief is, is de standaardwaarde voor start len(s) (terwijl end is niet gelijk aan 0, omdat s[::-1] s[0] bevat). Bijvoorbeeld:

s[::-1]            # Reversed slice
s[len(s)::-1]      # The same as above, reversed slice
s[0:len(s):-1]     # Empty list

Fout buiten bereik?

Wees verrast: slice geeft geen IndexError als de index buiten bereik is!

Als de index buiten bereik is, zal Python zijn best doen om de index in te stellen op 0 of len(s), afhankelijk van de situatie. Bijvoorbeeld:

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]

3. Voorbeelden

Laten we dit antwoord afmaken met voorbeelden, waarin we alles uitleggen wat we hebben besproken:

# 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

Antwoord 19

De vorige antwoorden gaan niet in op multidimensionale array-slicing, wat mogelijk is met de beroemde NumPy pakket:

Slicing kan ook worden toegepast op multidimensionale arrays.

# 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]])

De “:2” voor de komma werkt op de eerste dimensie en de “0:3:2” na de komma werkt op de tweede dimensie.

p>


Antwoord 20

Persoonlijk denk ik erover na als een for-lus:

a[start:end:step]
# for(i = start; i < end; i += step)

Houd er ook rekening mee dat negatieve waarden voor start en end relatief zijn aan het einde van de lijst en in het bovenstaande voorbeeld worden berekend door given_index + a.shape[0].


Antwoord 21

Naar mijn mening zul je de Python string slicing-notatie beter begrijpen en onthouden als je er op de volgende manier naar kijkt (lees verder).

Laten we met de volgende tekenreeks werken …

azString = "abcdefghijklmnopqrstuvwxyz"

Voor degenen die het niet weten, je kunt elke substring van azString maken met de notatie azString[x:y]

Als je uit andere programmeertalen komt, wordt het gezond verstand aangetast. Wat zijn x en y?

Ik moest gaan zitten en verschillende scenario’s uitvoeren in mijn zoektocht naar een memorisatietechniek die me helpt herinneren wat x en y zijn en me helpt om snaren bij de eerste poging goed te snijden.

Mijn conclusie is dat x en y moeten worden gezien als de grensindexen die de strings omringen die we willen toevoegen. We zouden de uitdrukking dus moeten zien als azString[index1, index2] of zelfs duidelijker als azString[index_of_first_character, index_after_the_last_character].

Hier is een voorbeeldvisualisatie van dat …

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

Dus alles wat je hoeft te doen is index1 en index2 in te stellen op de waarden die de gewenste substring omringen. Om bijvoorbeeld de substring “cdefgh” te krijgen, kunt u azString[2:8] gebruiken, omdat de index aan de linkerkant van “c” 2 is en die aan de rechterkant van ” h” is 8.

Vergeet niet dat we de grenzen aangeven. En die grenzen zijn de posities waar je enkele haakjes zou kunnen plaatsen die op deze manier rond de substring worden gewikkeld …

a b [ c d e f g h ] i j

Die truc werkt altijd en is gemakkelijk te onthouden.


Antwoord 22

#!/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)

Je kunt dit script uitvoeren en ermee experimenteren. Hieronder staan ​​enkele voorbeelden die ik van het script heb gekregen.

  +---+---+---+---+---+---+---+---+---+
  | 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]

Als u een negatieve stap gebruikt, let er dan op dat het antwoord met 1 naar rechts is verschoven.


Antwoord 23

Mijn brein lijkt blij te accepteren dat lst[start:end] het start-de item bevat. Ik zou zelfs kunnen zeggen dat het een ‘natuurlijke aanname’ is.

Maar af en toe sluipt er twijfel in en mijn brein vraagt ​​om geruststelling dat het niet het end-th element bevat.

Op deze momenten vertrouw ik op deze eenvoudige stelling:

for any n,    lst = lst[:n] + lst[n:]

Deze mooie eigenschap vertelt me ​​dat lst[start:end] het end-th item niet bevat omdat het in lst[end:].

Merk op dat deze stelling waar is voor elke n. U kunt bijvoorbeeld controleren of

lst = range(10)
lst[:-42] + lst[-42:] == lst

retourneert True.


Antwoord 24

Ik wil een Hallo wereld! voorbeeld toevoegen dat de basisprincipes van slices uitlegt voor de zeer beginners. Het heeft me erg geholpen.

Laten we een lijst hebben met zes waarden ['P', 'Y', 'T', 'H', 'O', 'N']:

+---+---+---+---+---+---+
| P | Y | T | H | O | N |
+---+---+---+---+---+---+
  0   1   2   3   4   5

De eenvoudigste segmenten van die lijst zijn de sublijsten. De notatie is [<index>:<index>] en de sleutel is om het als volgt te lezen:

[ start cutting before this index : end cutting before this index ]

Als je nu een plak [2:5] van de bovenstaande lijst maakt, gebeurt dit:

        |           |
+---+---|---+---+---|---+
| P | Y | T | H | O | N |
+---+---|---+---+---|---+
  0   1 | 2   3   4 | 5

Je hebt vóór het element met index 2 geknipt en nog een keer vóór het element met index 5 geknipt . Het resultaat is dus een plak tussen die twee sneden, een lijst ['T', 'H', 'O'].


Antwoord 25

In Python is de meest eenvoudige vorm voor slicen de volgende:

l[start:end]

waar l een verzameling is, start een inclusieve index is en end een exclusieve index is.

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]

Als je vanaf het begin segmenteert, kun je de nulindex weglaten en als je tot het einde doorsnijdt, kun je de laatste index weglaten omdat deze overbodig is, dus wees niet uitgebreid:

In [5]: l[:3] == l[0:3]
Out[5]: True
In [6]: l[7:] == l[7:len(l)]
Out[6]: True

Negatieve gehele getallen zijn handig bij het uitvoeren van offsets ten opzichte van het einde van een verzameling:

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]

Het is mogelijk om indices op te geven die buiten de grenzen vallen bij het slicen, zoals:

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]

Houd er rekening mee dat het resultaat van het opdelen van een verzameling een geheel nieuwe verzameling is. Bovendien hoeft bij het gebruik van plaknotatie in opdrachten de lengte van de plaktoekenningen niet hetzelfde te zijn. De waarden voor en na het toegewezen segment blijven behouden en de verzameling wordt kleiner of groter om de nieuwe waarden te bevatten:

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]

Als u de begin- en eindindex weglaat, maakt u een kopie van de verzameling:

In [14]: l_copy = l[:]
In [15]: l == l_copy and l is not l_copy
Out[15]: True

Als de begin- en eindindexen worden weggelaten bij het uitvoeren van een toewijzingsbewerking, wordt de volledige inhoud van de verzameling vervangen door een kopie van waarnaar wordt verwezen:

In [20]: l[:] = list('hello...')
In [21]: l
Out[21]: ['h', 'e', 'l', 'l', 'o', '.', '.', '.']

Naast het basis snijden, is het ook mogelijk om de volgende notatie toe te passen:

l[start:end:step]

waar l een verzameling is, start een inclusieve index is, end een exclusieve index is en step is een stap die kan worden gebruikt om elk nde item in l te nemen.

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]

Het gebruik van step biedt een handige truc om een ​​verzameling in Python ongedaan te maken:

In [25]: l[::-1]
Out[25]: [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]

Het is ook mogelijk om negatieve gehele getallen te gebruiken voor step zoals in het volgende voorbeeld:

In[28]:  l[::-2]
Out[28]: [9, 7, 5, 3, 1]

Het gebruik van een negatieve waarde voor step kan echter erg verwarrend zijn. Bovendien, om Pythonic te zijn, moet je het gebruik van start, end en step in één slice. Als dit nodig is, overweeg dan om dit in twee opdrachten te doen (een om te slicen en de andere om te schrijden).

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]

Antwoord 26

De meeste van de vorige antwoorden verduidelijken vragen over plaknotatie.

De uitgebreide indexeringssyntaxis die voor het slicen wordt gebruikt, is aList[start:stop:step], en basisvoorbeelden zijn:

Voer hier de afbeeldingsbeschrijving in:

Meer voorbeelden van slicen: 15 Extended Slices


Antwoord 27

Het onderstaande is het voorbeeld van een index van een string:

 +---+---+---+---+---+
 | H | e | l | p | A |
 +---+---+---+---+---+
 0   1   2   3   4   5
-5  -4  -3  -2  -1
str="Name string"

Snijvoorbeeld: [start:end:step]

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

Hieronder staat het voorbeeldgebruik:

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

Antwoord 28

Als je denkt dat negatieve indices bij slicen verwarrend zijn, is hier een heel eenvoudige manier om erover na te denken: vervang gewoon de negatieve index door len - index. Vervang bijvoorbeeld -3 door len(list) - 3.

De beste manier om te illustreren wat slicing intern doet, is door het in code weer te geven die deze bewerking implementeert:

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)]

Antwoord 29

De basistechniek voor het snijden is het definiëren van het startpunt, het stoppunt en de stapgrootte – ook bekend als stride.

Eerst zullen we een lijst met waarden maken om te gebruiken in onze slicing.

Maak twee lijsten om te segmenteren. De eerste is een numerieke lijst van 1 tot 9 (Lijst A). De tweede is ook een numerieke lijst, van 0 tot 9 (Lijst 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)

Indexeer het cijfer 3 van A en het cijfer 6 van B.

print(A[2])
print(B[6])

Basissnijden

Uitgebreide indexeringssyntaxis die wordt gebruikt voor slicen is aList[start:stop:step]. Het startargument en het stapargument zijn beide standaard ingesteld op geen – het enige vereiste argument is stop. Is het je opgevallen dat dit vergelijkbaar is met hoe het bereik werd gebruikt om lijsten A en B te definiëren? Dit komt omdat het slice-object de set indexen vertegenwoordigt die zijn gespecificeerd op bereik (start, stop, step). Python 3.4-documentatie.

Zoals je kunt zien, retourneert het definiëren van alleen stop één element. Aangezien de start standaard op geen staat, vertaalt dit zich in het ophalen van slechts één element.

Het is belangrijk op te merken dat het eerste element index 0 is, niet index 1. Daarom gebruiken we voor deze oefening 2 lijsten. De elementen van lijst A zijn genummerd volgens de rangschikking (het eerste element is 1, het tweede element is 2, enz.) terwijl de elementen van lijst B de nummers zijn die zouden worden gebruikt om ze te indexeren ([0] voor het eerste element 0, enz.).

Met de uitgebreide indexeringssyntaxis halen we een reeks waarden op. Alle waarden worden bijvoorbeeld opgehaald met een dubbele punt.

A[:]

Om een ​​subset van elementen op te halen, moeten de start- en stopposities worden gedefinieerd.

Gegeven het patroon aList[start:stop], haal de eerste twee elementen op uit lijst A.


Antwoord 30

Ik denk niet dat het diagram Python-tutorial ( geciteerd in verschillende andere antwoorden) is goed omdat deze suggestie werkt voor een positieve pas, maar niet voor een negatieve pas.

Dit is het diagram:

 +---+---+---+---+---+---+
 | P | y | t | h | o | n |
 +---+---+---+---+---+---+
 0   1   2   3   4   5   6
-6  -5  -4  -3  -2  -1

Uit het diagram verwacht ik dat a[-4,-6,-1] yP is, maar het is ty.

>>> a = "Python"
>>> a[2:4:1] # as expected
'th'
>>> a[-4:-6:-1] # off by 1
'ty'

Wat altijd werkt is om in karakters of slots te denken en indexering te gebruiken als een half-open interval — rechts open bij positieve pas, links open als negatieve pas.

Op deze manier kan ik a[-4:-6:-1] zien als a(-6,-4] in intervalterminologie.

 +---+---+---+---+---+---+
 | 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  

LEAVE A REPLY

Please enter your comment!
Please enter your name here

twenty + 3 =

Other episodes