diff --git a/Lib/test/test_range.py b/Lib/test/test_range.py index 3870b153688b25..395652f24b7bff 100644 --- a/Lib/test/test_range.py +++ b/Lib/test/test_range.py @@ -584,6 +584,17 @@ def check(start, stop, step=None): check(0, -1) check(-1, -3, -1) + for test in (range(5), range(0), range(1, 10, 2), range(10, 0, -1), range(-1, 200, 1)): + with self.subTest(test=test): + self.assertIs(test, test[:]) + self.assertIs(test, test[:len(test):]) + self.assertIs(test, test[0:len(test):1]) + + if len(test) > 1: + self.assertIsNot(test, test[1:len(test):2]) + self.assertIsNot(test, test[1:]) + self.assertIsNot(test, test[:-1]) + def test_contains(self): r = range(10) self.assertIn(0, r) diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2025-10-04-14-06-40.gh-issue-139476.02iIfn.rst b/Misc/NEWS.d/next/Core_and_Builtins/2025-10-04-14-06-40.gh-issue-139476.02iIfn.rst new file mode 100644 index 00000000000000..4864b5b51d31e9 --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2025-10-04-14-06-40.gh-issue-139476.02iIfn.rst @@ -0,0 +1,2 @@ +:func:`range` slicing with ``[:]`` and ``[:len(r):]`` no longer creates a copy, +it now returns the same object, consistent with :func:`copy.copy`. diff --git a/Objects/rangeobject.c b/Objects/rangeobject.c index f8cdfe68a6435e..b15fc11a20cbcc 100644 --- a/Objects/rangeobject.c +++ b/Objects/rangeobject.c @@ -413,6 +413,13 @@ compute_slice(rangeobject *r, PyObject *_slice) if (error == -1) return NULL; + if (start == _PyLong_GetZero() + && step == _PyLong_GetOne() + && (slice->stop == Py_None || PyObject_RichCompareBool(stop, r->length, Py_EQ) == 1)) + { + return Py_NewRef(r); + } + substep = PyNumber_Multiply(r->step, step); if (substep == NULL) goto fail; Py_CLEAR(step);