In Python (2 und 3). Immer wenn wir List Slicing verwenden, wird ein neues Objekt zurückgegeben, z.
l1 = [1,2,3,4]
print(id(l1))
l2 = l1[:]
print(id(l2))
Ausgabe
>>> 140344378384464
>>> 140344378387272
Wenn dasselbe mit Tupel wiederholt wird, wird dasselbe Objekt zurückgegeben, z.
t1 = (1,2,3,4)
t2 = t1[:]
print(id(t1))
print(id(t2))
Ausgabe
>>> 140344379214896
>>> 140344379214896
Es wäre großartig, wenn jemand etwas Licht ins Dunkel bringen könnte, warum dies geschieht. Während meiner gesamten Python-Erfahrung hatte ich den Eindruck, dass ein leeres Slice ein neues Objekt zurückgibt.
Mein Verständnis ist, dass es dasselbe Objekt zurückgibt, da Tupel unveränderlich sind und es keinen Sinn macht, eine neue Kopie davon zu erstellen. Aber auch hier wird es nirgendwo in den Dokumenten erwähnt.
l2 = tuple(iter(l1))
umgeht die OptimierungPyTuple_GetSlice
ungenau dokumentiert wurde, nachdem Ihre Frage angezeigt wurde. Die Dokumente wurden jetzt behoben (dies war das bpo-Problem 38557 ).Antworten:
Implementierungen können identische Instanzen für unveränderliche Typen zurückgeben (in CPython werden manchmal ähnliche Optimierungen für Zeichenfolgen und Ganzzahlen angezeigt). Da das Objekt nicht geändert werden kann, muss im Benutzercode nichts berücksichtigt werden, ob es eine eindeutige Instanz oder nur einen anderen Verweis auf eine vorhandene Instanz enthält.
Den Kurzschluss finden Sie im C-Code hier .
Dies ist ein Implementierungsdetail. Beachten Sie, dass Pypy nicht dasselbe tut.
quelle
a->ob_item
ist(*a).ob_item
also so, als würde das Mitgliedob_item
von dem aufgerufen, auf dasPyTupleObject
a zeigt, und das + ilow rückt dann zum Anfang des Slice vor.Es ist ein Implementierungsdetail. Da Listen veränderbar sind,
l1[:]
muss eine Kopie erstellt werden, da Sie keinel2
Auswirkungen erwarten würdenl1
.Da ein Tupel jedoch unveränderlich ist , können Sie nichts tun,
t2
was sich auft1
sichtbare Weise auswirken würde. Daher kann der Compiler das gleiche Objekt für und verwenden (ist jedoch nicht erforderlich ) .t1
t1[:]
quelle
In Python 3. *
my_list[:]
ist syntaktischer Zucker fürtype(my_list).__getitem__(mylist, slice_object)
where:slice_object
ist ein Slice-Objekt, das ausmy_list
den Attributen (Länge) und dem Ausdruck erstellt wird[:]
. Objekte, die sich so verhalten, werden im Python-Datenmodell als subskriptierbar bezeichnet (siehe hier) . Für Listen und Tupel__getitem__
ist eine integrierte Methode.In CPython und für Listen und Tupel
__getitem__
wird dies durch die Bytecode-Operation interpretiert, dieBINARY_SUBSCR
für Tupel hier und für Listen hier implementiert ist .Im Fall von Tupeln, zu Fuß durch den Code sehen Sie , dass in diesem Codeblock ,
static PyObject* tuplesubscript(PyTupleObject* self, PyObject* item)
einen Verweis auf den gleichen zurückgeben ,PyTupleObject
dass sie als Eingabeargument bekommen, wenn Einzelteil vom TypPySlice
und die Scheibe auswertet auf das gesamte Tupel.Jetzt überprüfen Sie den Code
static PyObject * list_subscript(PyListObject* self, PyObject* item)
und stellen selbst fest, dass unabhängig vom Slice immer ein neues Listenobjekt zurückgegeben wird.quelle
start:stop
Slice für den integrierten Typ, einschließlichtup[:]
, nicht übergehtBINARY_SUBSCR
. Das erweiterte Slicing wirdstart:stop:step
jedoch abonniert.Ich bin mir nicht sicher, aber es scheint, dass Python Ihnen einen neuen Zeiger auf dasselbe Objekt bietet, um das Kopieren zu vermeiden, da die Tupel identisch sind (und da das Objekt ein Tupel ist, ist es unveränderlich).
quelle