This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

classification
Title: heapq.heappop - documentation misleading or doesn't work
Type: behavior Stage: resolved
Components: Documentation Versions: Python 3.6
process
Status: closed Resolution: rejected
Dependencies: Superseder:
Assigned To: rhettinger Nosy List: abcdef, docs@python, eric.smith, r.david.murray, rhettinger, scooter4j
Priority: normal Keywords:

Created on 2017-11-26 16:05 by scooter4j, last changed 2022-04-11 14:58 by admin. This issue is now closed.

Messages (7)
msg307006 - (view) Author: Scott Queen (scooter4j) Date: 2017-11-26 16:05
The documentation for heapq.heappop(heap) says:
"Pop and return the smallest item from the heap, maintaining the heap invariant. If the heap is empty, IndexError is raised. To access the smallest item without popping it, use heap[0]."

yet, in the following code, the resultant heap doesn't reflect the heap invariant:

import heapq
li = [5, 7, 9, 1, 4, 3]
heapq.heapify(li)
#change a couple values in the heap
li[3] = 16
li[4] = 2
print (heapq.heappop(li))
print ("The heap after pop is : ",end="")
print (list(li))

This prints: The heap after pop is : [3, 4, 9, 16, 2]

The documentation implies to me that heapify would be called internally after heappop, but I may be misreading. Perhaps heappop could say that the heap invariant is maintained if the heap is properly sorted before the heappop invocation.
msg307008 - (view) Author: Eric V. Smith (eric.smith) * (Python committer) Date: 2017-11-26 16:24
The heap invariant is also required in order to even meet the documented behavior of returning the smallest item.

>>> import heapq
>>> li = [5, 7, 9, 1, 4, 3]
>>> heapq.heapify(li)
>>> li
[1, 4, 3, 7, 5, 9]
>>> li[2] = 0
>>> heapq.heappop(li)
1
>>> li
[0, 4, 9, 7, 5]
>>>

I guess the argument could be made that docs say "from the heap", and by modifying the list yourself it's no longer a heap.
msg307011 - (view) Author: (abcdef) Date: 2017-11-26 17:51
>  Perhaps heappop could say that the heap invariant is maintained if the heap is properly sorted before the heappop invocation.

Honestly I like this wording less. "Properly sorted" would suggest sorted in the sense of heap.sort() [as the docs refer to this earlier], but the array doesn't have to be sorted; it's enough if it's a heap. The function always maintains the invariant - this means that if the invariant is true as a precondition, it will be true as a postcondition. Maybe you have a different idea?
msg307017 - (view) Author: Eric V. Smith (eric.smith) * (Python committer) Date: 2017-11-26 20:24
By "sorted" I meant "sorted by the heap functions so as to maintain their invariants".

I don't have any suggestion for the actual specific language to use.
msg307034 - (view) Author: Scott Queen (scooter4j) Date: 2017-11-27 04:58
Fair statement. "Properly sorted" was a poor choice. Seems that "if the
invariant is true as a precondition, it will be true as a postcondition" is
accurate and descriptive -  maybe with a caution that modifying the list
(heap) values by means other than the heapq functions are likely to render
the invariant false (the latter phrase being for somewhat newbies like me
who wouldn't realize this truth without having to learn it in the debugger).

On Sun, Nov 26, 2017 at 10:51 AM, abcdef <report@bugs.python.org> wrote:

>
> abcdef <x@mailinator.com> added the comment:
>
> >  Perhaps heappop could say that the heap invariant is maintained if the
> heap is properly sorted before the heappop invocation.
>
> Honestly I like this wording less. "Properly sorted" would suggest sorted
> in the sense of heap.sort() [as the docs refer to this earlier], but the
> array doesn't have to be sorted; it's enough if it's a heap. The function
> always maintains the invariant - this means that if the invariant is true
> as a precondition, it will be true as a postcondition. Maybe you have a
> different idea?
>
> ----------
> nosy: +abcdef
>
> _______________________________________
> Python tracker <report@bugs.python.org>
> <https://bugs.python.org/issue32142>
> _______________________________________
>
msg307318 - (view) Author: R. David Murray (r.david.murray) * (Python committer) Date: 2017-11-30 14:45
I would suggested following the statement "To create a heap, use a list initialized to [], or you can transform a populated list into a heap via function heapify()." with "Any mutation of the list thereafter must maintain the heap invariant in order for the list to remain a heap."
msg320363 - (view) Author: Raymond Hettinger (rhettinger) * (Python committer) Date: 2018-06-24 07:13
We could apply David Murray's suggested wording but I don't think it would actually help anyone.  There are worked out examples from basic to advanced and a detailed section on the theory as well.

ISTM, that prior to reading the docs, the OP likely already had an incorrect mental model that caused the misreading of "maintaining" as "restoring".

For the most part, these docs have stood the test of time.  I don't see any StackOverflow questions about this either.  I recommend marking this as closed (the OP seems to now have a clear understanding of this so there isn't an open problem to be resolved).
History
Date User Action Args
2022-04-11 14:58:54adminsetgithub: 76323
2019-03-21 19:48:37cheryl.sabellasetstatus: open -> closed
resolution: rejected
stage: resolved
2018-06-24 07:13:56rhettingersetmessages: + msg320363
2017-11-30 14:45:01r.david.murraysetnosy: + r.david.murray
messages: + msg307318
2017-11-27 23:20:28rhettingersetassignee: docs@python -> rhettinger

nosy: + rhettinger
2017-11-27 04:58:51scooter4jsetmessages: + msg307034
2017-11-26 20:24:25eric.smithsetmessages: + msg307017
2017-11-26 17:51:24abcdefsetnosy: + abcdef
messages: + msg307011
2017-11-26 16:24:10eric.smithsetnosy: + eric.smith
messages: + msg307008
2017-11-26 16:05:48scooter4jcreate