diff --git a/Lib/test/test_memoryview.py b/Lib/test/test_memoryview.py index 656318668e6d6e..5aa2b0ecd6767d 100644 --- a/Lib/test/test_memoryview.py +++ b/Lib/test/test_memoryview.py @@ -575,6 +575,27 @@ def test_array_assign(self): m[:] = new_a self.assertEqual(a, new_a) + def test_compare_equal(self): + # A memoryview is equal to itself: there is no need to compare + # individual values. This is not true for float values since they can + # be NaN, and NaN is not equal to itself. + for int_format in 'bBhHiIlLqQ': + with self.subTest(format=int_format): + a = array.array(int_format, [1, 2, 3]) + m = memoryview(a) + self.assertTrue(m == m) + + for float_format in 'fd': + with self.subTest(format=int_format): + a = array.array(float_format, [1.0, 2.0, float('nan')]) + m = memoryview(a) + # nan is not equal to nan + self.assertFalse(m == m) + + a = array.array(float_format, [1.0, 2.0, 3.0]) + m = memoryview(a) + self.assertTrue(m == m) + class BytesMemorySliceTest(unittest.TestCase, BaseMemorySliceTests, BaseBytesMemoryTests): diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-02-19-12-49-15.gh-issue-144995.Ob2oYJ.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-02-19-12-49-15.gh-issue-144995.Ob2oYJ.rst new file mode 100644 index 00000000000000..83d84b9505c5a5 --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2026-02-19-12-49-15.gh-issue-144995.Ob2oYJ.rst @@ -0,0 +1,2 @@ +Optimize :class:`memoryview` comparison: a :class:`memoryview` is equal to +itself, there is no need to compare values. Patch by Victor Stinner. diff --git a/Objects/memoryobject.c b/Objects/memoryobject.c index f3b7e4a396b4a1..76ac3f4d059c60 100644 --- a/Objects/memoryobject.c +++ b/Objects/memoryobject.c @@ -3122,6 +3122,29 @@ memory_richcompare(PyObject *v, PyObject *w, int op) } vv = VIEW_ADDR(v); + // For formats supported by the struct module a memoryview is equal to + // itself: there is no need to compare individual values. + // This is not true for float values since they can be NaN, and NaN + // is not equal to itself. So only use this optimization on format known to + // not use floats. + if (v == w) { + int can_compare_ptr; + const char *format = vv->format; + if (format != NULL) { + // Include only formats known by struct, exclude formats "d" (double), + // "f" (float), "e" (16-bit float) and "P" (void*) + can_compare_ptr = (strchr("bBchHiIlLnNqQ?", format[0]) != NULL + && format[1] == 0); + } + else { + can_compare_ptr = 1; + } + if (can_compare_ptr) { + equal = 1; + goto result; + } + } + if (PyMemoryView_Check(w)) { if (BASE_INACCESSIBLE(w)) { equal = (v == w);