Was ist der Unterschied zwischen der Slice-Zuweisung, die die gesamte Liste aufteilt, und der direkten Zuweisung?

Lesezeit: 4 Minuten

Benutzer-Avatar
0xc0de

Ich sehe an vielen Stellen die Verwendung von Slice-Zuweisungen für lists. Ich kann seine Verwendung verstehen, wenn er mit (nicht standardmäßigen) Indizes verwendet wird, aber ich kann seine Verwendung nicht verstehen wie:

a_list[:] = ['foo', 'bar']

Wie unterscheidet sich das von

a_list = ['foo', 'bar']

?

Benutzer-Avatar
agf

a_list = ['foo', 'bar']

Erstellt ein neues list in Erinnerung und zeigt den Namen a_list daran. Es ist unerheblich was a_list vorher hingewiesen.

a_list[:] = ['foo', 'bar']

Ruft die an __setitem__ Methode der a_list Objekt mit a slice als Index und eine neue list als Wert im Speicher angelegt.

__setitem__ wertet die slice um herauszufinden, welche Indizes es darstellt, und ruft auf iter auf den Wert, der übergeben wurde. Anschließend wird das Objekt durchlaufen, wobei jeder Index innerhalb des durch die angegebenen Bereichs festgelegt wird slice zum nächsten Wert aus dem Objekt. Zum lists, wenn der von der angegebene Bereich slice hat nicht die gleiche Länge wie das Iterable, das list wird verkleinert. Dadurch können Sie eine Reihe interessanter Dinge tun, z. B. Abschnitte einer Liste löschen:

a_list[:] = [] # deletes all the items in the list, equivalent to 'del a_list[:]'

oder Einfügen neuer Werte in die Mitte einer Liste:

a_list[1:1] = [1, 2, 3] # inserts the new values at index 1 in the list

Allerdings mit “erweiterten Slices”, wo die step nicht eins ist, muss das Iterable die richtige Länge haben:

>>> lst = [1, 2, 3]
>>> lst[::2] = []
Traceback (most recent call last):
  File "<interactive input>", line 1, in <module>
ValueError: attempt to assign sequence of size 0 to extended slice of size 2

Die wichtigsten Dinge, die sich bei der Slice-Zuweisung unterscheiden a_list sind:

  1. a_list muss bereits auf ein Objekt zeigen
  2. Dieses Objekt wird modifiziert, anstatt darauf zu zeigen a_list an einem neuen Objekt
  3. Dieses Objekt muss unterstützen __setitem__ mit einer slice Index
  4. Das Objekt auf der rechten Seite muss die Iteration unterstützen
  5. Auf das Objekt auf der rechten Seite wird kein Name gezeigt. Wenn es keine anderen Verweise darauf gibt (z. B. wenn es sich wie in Ihrem Beispiel um ein Literal handelt), wird es nach Abschluss der Iteration als Verweis nicht mehr existierend gezählt.

  • Ich habe das in den Dokumenten gelesen (docs.python.org/tutorial/introduction.html#lists). Nur der Standardindex war mein Zweifel 🙂

    – 0xc0de

    14. April 2012 um 19:00 Uhr

  • “Wenn bei Listen der durch das Segment angegebene Bereich nicht dieselbe Länge wie das Iterable hat, wird die Größe der Liste geändert.” Dies gilt nur, wenn der Schrittwert des Bereichs 1 ist. Für andere Schrittwerte als 1 muss die zugewiesene Iterable die richtige Anzahl von Elementen ergeben.

    – Sven Marnach

    15. April 2012 um 16:57 Uhr

  • @SvenMarnach Danke. Ich habe das am Ende angehängt, weil ich vergessen hatte, es zu erwähnen, und ich wusste, dass es Situationen gab, in denen es die gleiche Länge haben musste.

    – agf

    15. April 2012 um 18:40 Uhr

Benutzer-Avatar
Jochen Ritzel

Der Unterschied ist ziemlich groß! Im

a_list[:] = ['foo', 'bar']

Sie ändern eine vorhandene Liste, die an den Namen gebunden war a_list. Auf der anderen Seite,

a_list = ['foo', 'bar']

weist dem Namen eine neue Liste zu a_list.

Vielleicht hilft das:

a = a_list = ['foo', 'bar'] # another name for the same list
a_list = ['x', 'y'] # reassigns the name a_list
print a # still the original list

a = a_list = ['foo', 'bar']
a_list[:] = ['x', 'y'] # changes the existing list bound to a
print a # a changed too since you changed the object

Durch die Zuordnung zu a_list[:], a_list immer noch Verweis auf dasselbe Listenobjekt, mit geändertem Inhalt. Durch die Zuordnung zu a_list, a_list jetzt Verweis auf ein neues Listenobjekt.

Schauen Sie sich seine an id:

>>> a_list = []
>>> id(a_list)
32092040
>>> a_list[:] = ['foo', 'bar']
>>> id(a_list)
32092040
>>> a_list = ['foo', 'bar']
>>> id(a_list)
35465096

Wie Sie sehen können, ist es id ändert sich nicht mit der Slice-Zuweisungsversion.


Der Unterschied zwischen den beiden kann zu einem ganz anderen Ergebnis führen, beispielsweise wenn die Liste ein Parameter der Funktion ist:

def foo(a_list):
    a_list[:] = ['foo', 'bar']

a = ['original']
foo(a)
print(a)

Mit diesem, a wird ebenfalls modifiziert, aber wenn a_list = ['foo', 'bar'] wurden stattdessen verwendet, a behält seinen ursprünglichen Wert.

Benutzer-Avatar
Benutzer11817711

a_list = ['foo', 'bar']
a=a_list[:]  # by this you get an exact copy of a_list 
print(a)
a=[1,2,3] # even if you modify a it will not affect a_list
print(a)
print(a_list)

1017670cookie-checkWas ist der Unterschied zwischen der Slice-Zuweisung, die die gesamte Liste aufteilt, und der direkten Zuweisung?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy