diff --git a/Lib/heapq.py b/Lib/heapq.py index a3af6dc05bff37..485944f2623ae6 100644 --- a/Lib/heapq.py +++ b/Lib/heapq.py @@ -480,6 +480,10 @@ def nsmallest(n, iterable, key=None): Equivalent to: sorted(iterable, key=key)[:n] """ + # Short-cut for n<=0 to avoid unnecessary work + if n <= 0: + return [] + # Short-cut for n==1 is to use min() if n == 1: it = iter(iterable) @@ -540,6 +544,10 @@ def nlargest(n, iterable, key=None): Equivalent to: sorted(iterable, key=key, reverse=True)[:n] """ + # Short-cut for n<=0 to avoid unnecessary work + if n <= 0: + return [] + # Short-cut for n==1 is to use max() if n == 1: it = iter(iterable) diff --git a/Misc/NEWS.d/next/Library/2026-03-19-00-00-00.gh-issue-110067.RWJ5vA7m.rst b/Misc/NEWS.d/next/Library/2026-03-19-00-00-00.gh-issue-110067.RWJ5vA7m.rst new file mode 100644 index 00000000000000..df94b8f84611e0 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-03-19-00-00-00.gh-issue-110067.RWJ5vA7m.rst @@ -0,0 +1,3 @@ +Add early return for ``n <= 0`` in :func:`heapq.nsmallest` and +:func:`heapq.nlargest`, and improve docstrings for :func:`heapq.heappop_max`, +:func:`heapq.heapreplace_max`, and :func:`heapq.heapify_max`. diff --git a/Modules/_heapqmodule.c b/Modules/_heapqmodule.c index 05d01acd77109b..81784f30a5b677 100644 --- a/Modules/_heapqmodule.c +++ b/Modules/_heapqmodule.c @@ -424,7 +424,8 @@ siftdown_max(PyListObject *heap, Py_ssize_t startpos, Py_ssize_t pos) newitem = arr[pos]; while (pos > startpos) { parentpos = (pos - 1) >> 1; - parent = Py_NewRef(arr[parentpos]); + parent = arr[parentpos]; + Py_INCREF(parent); Py_INCREF(newitem); cmp = PyObject_RichCompareBool(parent, newitem, Py_LT); Py_DECREF(parent); @@ -538,12 +539,12 @@ _heapq.heappop_max heap: object(subclass_of='&PyList_Type') / -Maxheap variant of heappop. +Pop the largest item off the max-heap, maintaining the heap invariant. [clinic start generated code]*/ static PyObject * _heapq_heappop_max_impl(PyObject *module, PyObject *heap) -/*[clinic end generated code: output=2f051195ab404b77 input=5d70c997798aec64]*/ +/*[clinic end generated code: output=2f051195ab404b77 input=edca3ff5d6aa11c6]*/ { return heappop_internal(heap, siftup_max); } @@ -556,12 +557,12 @@ _heapq.heapreplace_max item: object / -Maxheap variant of heapreplace. +Pop and return the largest item from the max-heap, and push the new item. [clinic start generated code]*/ static PyObject * _heapq_heapreplace_max_impl(PyObject *module, PyObject *heap, PyObject *item) -/*[clinic end generated code: output=8770778b5a9cbe9b input=fe70175356e4a649]*/ +/*[clinic end generated code: output=8770778b5a9cbe9b input=75b704b6f92beab9]*/ { return heapreplace_internal(heap, item, siftup_max); } @@ -573,12 +574,12 @@ _heapq.heapify_max heap: object(subclass_of='&PyList_Type') / -Maxheap variant of heapify. +Transform list into a max-heap, in-place, in O(len(heap)) time. [clinic start generated code]*/ static PyObject * _heapq_heapify_max_impl(PyObject *module, PyObject *heap) -/*[clinic end generated code: output=8401af3856529807 input=4eee63231e7d1573]*/ +/*[clinic end generated code: output=8401af3856529807 input=4e02ed8aa546fb8e]*/ { return heapify_internal(heap, siftup_max); } diff --git a/Modules/clinic/_heapqmodule.c.h b/Modules/clinic/_heapqmodule.c.h index b43155b6c24e3c..e6aad1545af6ef 100644 --- a/Modules/clinic/_heapqmodule.c.h +++ b/Modules/clinic/_heapqmodule.c.h @@ -226,7 +226,7 @@ PyDoc_STRVAR(_heapq_heappop_max__doc__, "heappop_max($module, heap, /)\n" "--\n" "\n" -"Maxheap variant of heappop."); +"Pop the largest item off the max-heap, maintaining the heap invariant."); #define _HEAPQ_HEAPPOP_MAX_METHODDEF \ {"heappop_max", (PyCFunction)_heapq_heappop_max, METH_O, _heapq_heappop_max__doc__}, @@ -257,7 +257,7 @@ PyDoc_STRVAR(_heapq_heapreplace_max__doc__, "heapreplace_max($module, heap, item, /)\n" "--\n" "\n" -"Maxheap variant of heapreplace."); +"Pop and return the largest item from the max-heap, and push the new item."); #define _HEAPQ_HEAPREPLACE_MAX_METHODDEF \ {"heapreplace_max", _PyCFunction_CAST(_heapq_heapreplace_max), METH_FASTCALL, _heapq_heapreplace_max__doc__}, @@ -293,7 +293,7 @@ PyDoc_STRVAR(_heapq_heapify_max__doc__, "heapify_max($module, heap, /)\n" "--\n" "\n" -"Maxheap variant of heapify."); +"Transform list into a max-heap, in-place, in O(len(heap)) time."); #define _HEAPQ_HEAPIFY_MAX_METHODDEF \ {"heapify_max", (PyCFunction)_heapq_heapify_max, METH_O, _heapq_heapify_max__doc__}, @@ -358,4 +358,4 @@ _heapq_heappushpop_max(PyObject *module, PyObject *const *args, Py_ssize_t nargs exit: return return_value; } -/*[clinic end generated code: output=e83d50002c29a96d input=a9049054013a1b77]*/ +/*[clinic end generated code: output=b1170d77557075f6 input=a9049054013a1b77]*/