Python (and me) getting confused finding keys

J

John

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
 
L

Lie Ryan

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
 
S

Steven D'Aprano

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:

.... 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)
........ 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/2007/01/immutable-instances-in-python.html
 
A

Alf P. Steinbach

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,483
Members
44,901
Latest member
Noble71S45

Latest Threads

Top