Python(2 and 3)です。リストスライスを使用すると、常に新しいオブジェクトが返されます。例:
l1 = [1,2,3,4]
print(id(l1))
l2 = l1[:]
print(id(l2))
出力
>>> 140344378384464
>>> 140344378387272
同じことをタプルで繰り返すと、同じオブジェクトが返されます。例:
t1 = (1,2,3,4)
t2 = t1[:]
print(id(t1))
print(id(t2))
出力
>>> 140344379214896
>>> 140344379214896
私のPythonの経験全体を通して、空のスライスが新しいオブジェクトを返すという印象を受けました。).
私の理解では、タプルは不変であるのと同じオブジェクトを返し、その新しいコピーを作成する意味はありません。しかし、繰り返しになりますが、ドキュメントのどこにも記載されていません。
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)
のコードを調べて、スライスが何であれ、新しいリストオブジェクトが常に返されることを確認します。
これについては不明ですが、Pythonは、同じオブジェクトへの新しいポインタを提供して、コピーを回避するためにタプルが同一であるため(オブジェクトはタプルであるため、不変です)のようです。