En Python (2 y 3). Cada vez que usamos el corte de lista, devuelve un nuevo objeto, por ejemplo:
l1 = [1,2,3,4]
print(id(l1))
l2 = l1[:]
print(id(l2))
Salida
>>> 140344378384464
>>> 140344378387272
Si se repite lo mismo con tupla, se devuelve el mismo objeto, por ejemplo:
t1 = (1,2,3,4)
t2 = t1[:]
print(id(t1))
print(id(t2))
Salida
>>> 140344379214896
>>> 140344379214896
Sería genial si alguien puede arrojar algo de luz sobre por qué está sucediendo esto, a lo largo de mi experiencia en Python tuve la impresión de que el segmento vacío devuelve un nuevo objeto.
Tengo entendido que está devolviendo el mismo objeto ya que las tuplas son inmutables y no tiene sentido crear una nueva copia. Pero, de nuevo, no se menciona en los documentos en ninguna parte.

l2 = tuple(iter(l1))omite la optimizaciónPyTuple_GetSlicese documentó de manera incorrecta después de ver su pregunta. Los documentos ahora se han solucionado (este era el problema bpo38557 ).Respuestas:
Las implementaciones son libres de devolver instancias idénticas para tipos inmutables (en CPython, a veces puede ver optimizaciones similares para cadenas y enteros). Como el objeto no se puede cambiar, no hay nada en el código de usuario que deba preocuparse si contiene una instancia única o simplemente otra referencia a una instancia existente.
Puede encontrar el cortocircuito en el código C aquí .
Este es un detalle de implementación, tenga en cuenta que pypy no hace lo mismo.
fuente
a->ob_itemes como(*a).ob_item, es decir, obtiene el miembro llamadoob_itemdesde elPyTupleObjectque está apuntando a, y el + ilow luego avanza al comienzo del segmento.Es un detalle de implementación. Debido a que las listas son mutables,
l1[:]debe crear una copia, ya que no esperaría que los cambiosl2afectenl1.Sin embargo, dado que una tupla es inmutable , no hay nada que pueda hacer
t2que afectet1de manera visible, por lo que el compilador es libre (pero no obligatorio ) de usar el mismo objeto parat1yt1[:].fuente
En Python 3. *
my_list[:]es el azúcar sintáctico paratype(my_list).__getitem__(mylist, slice_object)donde:slice_objectes un objeto de corte construido a partirmy_listde los atributos (longitud) y la expresión[:]. Los objetos que se comportan de esta manera se denominan subscriptables en el modelo de datos de Python, ver aquí . Para listas y tuplas__getitem__es un método incorporado.En CPython, y para listas y tuplas,
__getitem__se interpreta mediante la operación de código de bytesBINARY_SUBSCRque se implementa para las tuplas aquí y para las listas aquí .En el caso de las tuplas, al recorrer el código, verá que en este bloque de código ,
static PyObject* tuplesubscript(PyTupleObject* self, PyObject* item)devolverá una referencia al mismoPyTupleObjectque obtuvo como argumento de entrada, si el elemento es de tipoPySlicey el segmento se evalúa como la tupla completa.Ahora examina el código
static PyObject * list_subscript(PyListObject* self, PyObject* item)y comprueba por sí mismo que, sea cual sea el segmento, siempre se devuelve un nuevo objeto de lista.fuente
start:stopsegmento en el tipo incorporadotup[:], incluido , no pasaBINARY_SUBSCR. Sinstart:stop:stepembargo, el corte extendido pasa por suscripción.No estoy seguro de esto, pero parece que Python le proporciona un nuevo puntero al mismo objeto para evitar la copia, ya que las tuplas son idénticas (y dado que el objeto es una tupla, es inmutable).
fuente