Tuple slicing not returning a new object as opposed to list slicing

后端 未结 4 1007
抹茶落季
抹茶落季 2021-02-19 14:18

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

4条回答
  •  闹比i
    闹比i (楼主)
    2021-02-19 14:45

    In Python 3.* my_list[:] is syntactic sugar for type(my_list).__getitem__(mylist, slice_object) where: slice_object is a slice object built from my_list's attributes (length) and the expression [:]. Objects that behave this way are called subscriptable in the Python data model see here. For lists and tuples __getitem__ is a built-in method.

    In CPython, and for lists and tuples, __getitem__ is interpreted by the bytecode operation BINARY_SUBSCR which is implemented for tuples in here and for lists in here.

    In case of tuples, walking through the code you will see that in this code block, static PyObject* tuplesubscript(PyTupleObject* self, PyObject* item) will return a reference to the same PyTupleObject that it got as input argument, if item is of type PySlice and the slice evaluates to the whole tuple.

        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. */
            ...
    }
    

    Now you examine the code for static PyObject * list_subscript(PyListObject* self, PyObject* item) and see for yourself that whatever the slice, a new list object is always returned.

提交回复
热议问题