Velocity Reviews

Velocity Reviews (http://www.velocityreviews.com/forums/index.php)
-   Python (http://www.velocityreviews.com/forums/f43-python.html)
-   -   Python (and me) getting confused finding keys (http://www.velocityreviews.com/forums/t709537-python-and-me-getting-confused-finding-keys.html)

John 12-22-2009 04:33 PM

Python (and me) getting confused finding keys
 
Hi there,

I have a rather lengthy program that troubles me for quite some time. After
some debugging, I arrived at the following assertion error:

for e in edges.keys():
assert edges.has_key(e)

Oops!? Is there ANY way that something like this can possibly happen?

Cheers,
John

Lie Ryan 12-22-2009 06:42 PM

Re: Python (and me) getting confused finding keys
 
On 12/23/2009 3:33 AM, John wrote:
> Hi there,
>
> I have a rather lengthy program that troubles me for quite some time. After
> some debugging, I arrived at the following assertion error:
>
> for e in edges.keys():
> assert edges.has_key(e)
>
> Oops!? Is there ANY way that something like this can possibly happen?


in a multithreaded program, it's possible another thread erased 'e'
after the for-loop grabbed it but before the suite is executed.

but often you'll get something like this:
RuntimeError: dictionary changed size during iteration

Steven D'Aprano 12-22-2009 10:48 PM

Re: Python (and me) getting confused finding keys
 
On Tue, 22 Dec 2009 17:33:04 +0100, John wrote:

> Hi there,
>
> I have a rather lengthy program that troubles me for quite some time.
> After some debugging, I arrived at the following assertion error:
>
> for e in edges.keys():
> assert edges.has_key(e)
>
> Oops!? Is there ANY way that something like this can possibly happen?


In another post, you assert that:

(1) You aren't knowingly using threads, so it's not likely that another
thread is modifying edges.

(2) edges is a regular dictionary, not a custom mapping class.


In that case, I would say that the most likely culprit is that the edges
are mutable but given a hash function. I can reproduce the problem like
this:


>>> class Edge:

.... def __init__(self, start, finish):
.... self.ends = (start, finish)
.... def __eq__(self, other):
.... return self.ends == other.ends
.... def __hash__(self):
.... return hash(self.ends)
....
>>> edges = {Edge(1, 5): None}
>>> for e in edges:

.... assert e in edges # same as edges.has_key(e)
.... e.ends = (5, 6)
.... assert e in edges, "and now it's gone"
....
Traceback (most recent call last):
File "<stdin>", line 4, in <module>
AssertionError: and now it's gone



So the likely problem is that your edge type is mutable and being mutated.

Now, if your code snippet above:

for e in edges.keys():
assert edges.has_key(e)


is a literal copy-and-paste from the failing code, I can only assume that
the edge type __eq__ or __hash__ method mutates self.

The lesson of this? Do not make mutable classes hashable.

The obvious follow-up is to ask how to make an immutable class.

http://northernplanets.blogspot.com/...in-python.html



--
Steven

Alf P. Steinbach 12-23-2009 12:55 AM

Re: Python (and me) getting confused finding keys
 
* Steven D'Aprano:
>

[snip]
> The obvious follow-up is to ask how to make an immutable class.
>
> http://northernplanets.blogspot.com/...in-python.html


Thanks, I've been wondering about that.

By the way, the link at the bottom in the article you linked to, referring to an
earlier posting by Alex Martelli, was broken.

I believe it was the posting available here: <url:
http://www.opensubscriber.com/message/python-list@python.org/2659890.html>.


Cheers,

- Alf

John 12-23-2009 09:01 AM

Re: Python (and me) getting confused finding keys
 

> The lesson of this? Do not make mutable classes hashable.


That could be it! I'll try. Thanks a lot!

> The obvious follow-up is to ask how to make an immutable class.
>
> http://northernplanets.blogspot.com/...es-in-python.h
> tml
>



All times are GMT. The time now is 02:17 AM.

Powered by vBulletin®. Copyright ©2000 - 2014, vBulletin Solutions, Inc.
SEO by vBSEO ©2010, Crawlability, Inc.