In Python (2 and 3). Whenever we use list slicing it returns a new object, e.g.:
l1 = [1,2,3,4]
print(id(l1))
l2 = l1[:]
print(id(l2))
Output>
Implementations are free to return identical instances for immutable types (in CPython, you may sometimes see similar optimizations for strings and integers). Since the object can not be changed, there is nothing in user code that needs to care whether it holds a unique instance or just another reference to an existing instance.
You can find the short-circuit in the C code here.
static PyObject*
tuplesubscript(PyTupleObject* self, PyObject* item)
{
... /* note: irrelevant parts snipped out */
if (start == 0 && step == 1 &&
slicelength == PyTuple_GET_SIZE(self) &&
PyTuple_CheckExact(self)) {
Py_INCREF(self); /* <--- increase reference count */
return (PyObject *)self; /* <--- return another pointer to same */
}
...
This is an implementation detail, note that pypy does not do the same.