473,804 Members | 2,104 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

A note on heapq module

In few minutes I have just written this quite raw class, it lacks
doctring (the same of the functions of the heapq module), it may
contain bugs still, I haven't tested it much. It's just a simple
wrapper around some of the functions of the heapq module (nsmallest and
nlargest are missing). Usually I use classes only when I need then, I
like functional programming enough, and this class seems to just slow
down the functions of the heapq module. But I think an improved class
similar to this one may be useful (added, replacing isn't necessary)
into the heapq module, because it can avoid cetain errors: I know what
Heaps are and how they work, but some time ago I have written a bug
into small program that uses the functions of the heapq module, because
I have added an item to the head of the heap using a normal list
method, breaking the heap invariant. With a simple class like this one
all the methods of your object keep the heap invariant, avoiding that
kind of bugs. (If you are interested I can improve this class some,
it't not difficult.)
from heapq import heapify, heappush, heappop, heapreplace

class Heap(object):
def __init__(self, init=None):
if init is None:
self.h = []
elif isinstance(init , Heap):
self.h = init.h[:]
else:
self.h = list(init)
heapify(self.h)
def smallest(self):
return self.h[0]
def sort(self, cmp=None, key=None):
self.h.sort(cmp =cmp, key=key)
def heappush(self, item):
heappush(self.h , item)
def heappop(self):
return heappop(self.h)
def heapreplace(sel f, item):
return heapreplace(sel f.h, item)
def clear(self):
del self.h[:]
def __contains__(se lf, item):
return item in self.h
def __hash__(self):
raise TypeError("Heap objects are unhashable.")
def __iter__(self):
return self.h.__iter__ ()
def __eq__(self, other):
return isinstance(othe r, Heap) and self.h == other.h
def __ne__(self, other):
return not isinstance(othe r, Heap) or self.h != other.h
def __len__(self):
return len(self.h)
def __nonzero__(sel f):
return bool(self.h)
def __str__(self):
return str(self.h)
def __repr__(self):
return "Heap(%s)" % self.h if self.h else "Heap()"

Bye,
bearophile

Jan 16 '07 #1
18 2855
be************@ lycos.com wrote:
some time ago I have written a bug
into small program that uses the functions of the heapq module, because
I have added an item to the head of the heap using a normal list
method, breaking the heap invariant.
I know I've had similar bugs in my code before.
from heapq import heapify, heappush, heappop, heapreplace

class Heap(object):
[snip implementation]

+1 for adding a Heap object like this to the collections module. If you
can make a little time to add some tests (you could probably steal a lot
of what you need from test_heapq.py) you should definitely submit it as
a patch for 2.6.

STeVe
Jan 16 '07 #2
I think the sort has to be simplified, otherwise it can't keep the heap
invariant...

def sort(self):
self.h.sort()

Bye,
bearophile

Jan 16 '07 #3
be************@ lycos.com kirjoitti:
I think the sort has to be simplified, otherwise it can't keep the heap
invariant...

def sort(self):
self.h.sort()

Bye,
bearophile
And __repr__ should be something like this:
=========
def __repr__(self):
if self.h:
return "Heap(%s)" % self.h
else:
return "Heap()"
==========
to make it compatible with versions earlier than 2.5

Cheers,
Jussi
Jan 16 '07 #4
be************@ lycos.com wrote:
In few minutes I have just written this quite raw class, ....
I'd suggest some changes. It is nice to have Heaps with equal
contents equal no matter what order the inserts have been done.
Consider how you want Heap([1, 2, 3]) and Heap([3, 1, 2]) to behave.
Similarly, it is nice to have str and repr produce canonical
representations (I would skip the __str__ code, myself, though).
Also, subclasses should get their identities tweaked as so:
class Heap(object):
...
def sort(self, cmp=None, key=None):
self.h.sort(cmp =cmp, key=key)
I'd remove this method.
...
def __eq__(self, other):
return isinstance(othe r, Heap) and self.h == other.h
return isinstance(othe r, self.__class__) and sorted(
self.h) == sorted(other.h)
def __ne__(self, other):
return not isinstance(othe r, Heap) or self.h != other.h
return not isinstance(othe r, self.__class__) and sorted(
self.h) != sorted(other.h)
...
def __str__(self):
return str(self.h)
return str(sorted(self .h))
def __repr__(self):
return "Heap(%s)" % self.h if self.h else "Heap()"
return "%s(%s)" % (self.__class__ .__name__, sorted(self.h))
And I'd add:
def __lt__(self, other):
raise TypeError('no ordering relation is defined for %s'
% self.__class__. __name__)
__gt__ = __le__ = __ge__ = __lt__

--Scott David Daniels
sc***********@a cm.org
Jan 16 '07 #5
Scott David Daniels wrote:

Sorry, I blew the __ne__:
> def __ne__(self, other):
return not isinstance(othe r, Heap) or self.h != other.h
return not isinstance(othe r, self.__class__) and sorted(
self.h) != sorted(other.h)
Should be:
return not isinstance(othe r, self.__class__) or sorted(
self.h) != sorted(other.h)

--Scott David Daniels
sc***********@a cm.org
Jan 16 '07 #6
Scott David Daniels:
I'd suggest some changes. It is nice to have Heaps with equal
contents equal no matter what order the inserts have been done.
Consider how you want Heap([1, 2, 3]) and Heap([3, 1, 2]) to behave.
Similarly, it is nice to have str and repr produce canonical
representations (I would skip the __str__ code, myself, though).
Also, subclasses should get their identities tweaked as so:
My version was a *raw* one, just an idea, this is a bit better:
http://rafb.net/p/nLPPjo35.html
I like your changes. In the beginning I didn't want to put __eq__
__ne__ methods at all, because they are too much slow, but being them
O(n ln n) I think your solution is acceptable.

Some methods may have a name different from the heap functions:
def smallest(self):
def push(self, item):
def pop(self):
def replace(self, item):

Two things left I can see: I think the __init__ may have a boolean
inplace parameter to avoid copying the given list, so this class is
about as fast as the original heapify function (but maybe such thing is
too much dirty for a Python stdlib):

def __init__(self, sequence=None, inplace=False):
if sequence is None:
self._heap = []
elif isinstance(sequ ence, self.__class__) :
self._heap = sequence._heap[:]
else:
if inplace and isinstance(sequ ence, list):
self._heap = sequence
else:
self._heap = list(sequence)
heapify(self._h eap)

The second thing, I don't like much the __iter__ because it yields
unsorted items:

def __iter__(self):
return self._heap.__it er__()

Is this good? I think this can be accepted.

Thank you,
bye,
bearophile

Jan 16 '07 #7
On 2007-01-16, be************@ lycos.com <be************ @lycos.comwrote :
In few minutes I have just written this quite raw class, it lacks
doctring (the same of the functions of the heapq module), it may
contain bugs still, I haven't tested it much. It's just a simple
wrapper around some of the functions of the heapq module (nsmallest and
nlargest are missing). Usually I use classes only when I need then, I
like functional programming enough, and this class seems to just slow
down the functions of the heapq module. But I think an improved class
similar to this one may be useful (added, replacing isn't necessary)
into the heapq module, because it can avoid cetain errors: I know what
Heaps are and how they work, but some time ago I have written a bug
into small program that uses the functions of the heapq module, because
I have added an item to the head of the heap using a normal list
method, breaking the heap invariant. With a simple class like this one
all the methods of your object keep the heap invariant, avoiding that
kind of bugs. (If you are interested I can improve this class some,
it't not difficult.)

[ Heap class based on heapq ]
For me, your class has the same drawback as the heappush, heappop
procedurers: no way to specify a comparision function. Somewhere
in my experimental code I work with line segments in two dimensions.
Now in one place I want from the available segments the one in which the
first point is farthest to the left. In a second place I want from the
available segments the one in which the second point is farthest to the
left. Both can be done with a heap, but currently I can't get both
behaviours while using the same class and using the heapq module or
your Heap class.

--
Antoon Pardon
Jan 17 '07 #8
On 2007-01-16, be************@ lycos.com
<be************ @lycos.comwrote :
Scott David Daniels:
>I'd suggest some changes. It is nice to have Heaps with equal
contents equal no matter what order the inserts have been
done. Consider how you want Heap([1, 2, 3]) and Heap([3, 1,
2]) to behave. Similarly, it is nice to have str and repr
produce canonical representations (I would skip the __str__
code, myself, though). Also, subclasses should get their
identities tweaked as so:

My version was a *raw* one, just an idea, this is a bit better:
http://rafb.net/p/nLPPjo35.html
I like your changes. In the beginning I didn't want to put
__eq__ __ne__ methods at all, because they are too much slow,
but being them O(n ln n) I think your solution is acceptable.

Some methods may have a name different from the heap functions:
def smallest(self):
def push(self, item):
def pop(self):
def replace(self, item):

Two things left I can see: I think the __init__ may have a
boolean inplace parameter to avoid copying the given list, so
this class is about as fast as the original heapify function
(but maybe such thing is too much dirty for a Python stdlib):
One more idea, cribbed from the linked list thread elsewhere: it
might be nice if your Heap could optionally use an underlying
collections.deq ue instead of a list.

I don't know how excellent Python's deque is, but it's possible a
deque would provide a faster heap than a contiguous array. C++'s
std::deque is the default implementation of C++'s
std::priority_q ueue for that reason (unless I'm confused again).

--
Neil Cerutti
We will sell gasoline to anyone in a glass container. --sign at Santa Fe gas
station
Jan 17 '07 #9
Antoon Pardon wrote:
For me, your class has the same drawback as the heappush, heappop
procedurers: no way to specify a comparision function.
Agreed. I'd love to see something like ``Heap(key=my_k ey_func)``.

STeVe
Jan 17 '07 #10

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

0
1346
by: Eric | last post by:
I'm missing something critical about how heapq works. I assumed I could iterate through the heap, but I get partial iteration: >>> listB >>> heapify(listB) >>> for h in listB: m=heappop(listB) print m, '\t',listB
0
1430
by: Stefan Behnel | last post by:
Hi! I filed a patch for a Heap class to be integrated into the heapq module (in addition the the currently available functions). The main features are support for iteration and for the standard keyword arguments of sort() and sorted(): key, cmp, reverse. http://sourceforge.net/tracker/index.php?func=detail&aid=1162363&group_id=5470&atid=305470 I wrote it because I believe that it makes the API of that module much simpler
2
1519
by: Just Me | last post by:
When I print QueryPageSettings gets called a few times before PrintPage is called. I just occurred to me that the problem may be that I do AddHandler each time I print. Is that wrong? If so, is there something I can check to see if a handler has already been added?
3
1177
by: bearophileHUGS | last post by:
I don't like much the syntax of: if __name__ == '__main__': Some time ago I have read this PEP: http://www.python.org/dev/peps/pep-0299/ And why it was refused: http://mail.python.org/pipermail/python-dev/2006-March/062955.html I think the name of the standard main function may be just main(), so
2
1884
bartonc
by: bartonc | last post by:
>>> import string >>> help(string) Help on module string: NAME string - A collection of string operations (most are no longer used). FILE d:\python25\lib\string.py
2
4145
by: jm.suresh | last post by:
I wanted to have a heap of custom objects, and in different heaps I wanted to have the weights for my elements differently. So, I modified the heapq module to accept key arguments also. The untested code is here. Please let me know if you find any bug or if there is an easy way to do this. - Suresh...
1
3225
by: Davy | last post by:
Hi all, I have a dictionary with n elements, and I want to get the m(m<=n) keys with the largest values. For example, I have dic that includes n=4 elements, I want m=2 keys have the largest values) dic = {0:4,3:1,5:2,7:8} So, the the largest values are , so the keys are .
4
1477
by: George Sakkis | last post by:
I spent several hours debugging some bogus data results that turned out to be caused by the fact that heapq.nlargest doesn't respect rich comparisons: import heapq import random class X(object): def __init__(self, x): self.x=x def __repr__(self): return 'X(%s)' % self.x
7
4172
by: Giampaolo Rodola' | last post by:
Hi, this is related to what I'm trying to implement here: http://groups.google.com/group/comp.lang.python/browse_thread/thread/20796724c1daf1e1# My question is the following: is it safe to avoid to re-heapify() a heap when I remove or move an element which is not the first one? Example: Thanks in advance.
0
9595
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language synchronization. With a Microsoft account, language settings sync across devices. To prevent any complications,...
0
10600
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. Here is my compilation command: g++-12 -std=c++20 -Wnarrowing bit_field.cpp Here is the code in...
1
10354
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For most users, this new feature is actually very convenient. If you want to control the update process,...
0
10097
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the choice of these technologies. I'm particularly interested in Zigbee because I've heard it does some...
0
9175
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then launch it, all on its own.... Now, this would greatly impact the work of software developers. The idea...
0
6867
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert into image. Globals.ThisAddIn.Application.ActiveDocument.Select();...
0
5535
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in the same network. But I'm wondering if it's possible to do the same thing, with 2 Pfsense firewalls...
1
4313
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
2
3835
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.