В Python 3. * my_list[:]
- синтаксический сахар для type(my_list).__getitem__(mylist, slice_object)
, где: slice_object
- объект среза, построенный из атрибутов (длины) my_list
и выражения [:]
. Объекты, которые ведут себя таким образом, называются подписанными в модели данных Python, см. здесь . Для списков и кортежей __getitem__
- это встроенный метод.
В CPython и для списков и кортежей __getitem__
интерпретируется операцией байт-кода BINARY_SUBSCR
, которая реализована для кортежей здесь и для списков здесь .
В случае кортежей, проходя по коду, вы увидите, что в этот блок кода , static PyObject*
tuplesubscript(PyTupleObject* self, PyObject* item)
будет возвращать ссылку на тот же PyTupleObject
, который он получил в качестве входного аргумента,если элемент имеет тип PySlice
и срез оценивается как весь кортеж.
static PyObject*
tuplesubscript(PyTupleObject* self, PyObject* item)
{
/* checks if item is an index */
if (PyIndex_Check(item)) {
...
}
/* else it is a slice */
else if (PySlice_Check(item)) {
...
/* unpacks the slice into start, stop and step */
if (PySlice_Unpack(item, &start, &stop, &step) < 0) {
return NULL;
}
...
}
/* if we start at 0, step by 1 and end by the end of the tuple then !! look down */
else if (start == 0 && step == 1 &&
slicelength == PyTuple_GET_SIZE(self) &&
PyTuple_CheckExact(self)) {
Py_INCREF(self); /* increase the reference count for the tuple */
return (PyObject *)self; /* and return a reference to the same tuple. */
...
}
Теперь вы изучите код для static PyObject *
list_subscript(PyListObject* self, PyObject* item)
и убедитесь, что независимо от фрагмента, всегда возвращается новый объект списка.