Unexpected behavior with dictionary keys containment and a user-defined class
Steven D'Aprano
steven at REMOVE.THIS.cybersource.com.au
Mon Jan 12 23:05:57 EST 2009
On Mon, 12 Jan 2009 22:41:00 -0500, Rob Clewley wrote:
> Hi, the short version of my question is: when is a dictionary's
> __contains__ method behavior different to using the 'in' idiom? (because
> I have an example of a difference in my code).
[...]
> i in d.keys() and d.keys()[10] == i
>
> both return True. But
>
> d.__contains__(i)
> d.has_key(i)
> d.keys()[10] is i
The instance you are testing for isn't the same instance as the one in
the dictionary. It might be *equal*, but it isn't identical, and by
default, hashing of classes goes by identity. You need to give your class
a hash function so that whenever x==y hash(x)==hash(y) as well.
That means you need to over-ride __hash__(self) in the class.
> return False. I put a print statement in my class's __eq__ method and it
> is being called. It tests equality of some of my class instance's
> attributes. I didn't realize there was any situation where you could
> expect different results from i in d versus i in d.keys() -- am
> I misunderstanding something?
i in d.keys() does an item-by-item equality test, returning the first
time i is equal to an item.
i in d hashes i, then looks up a table to see whether there is an item in
that spot. If there is, it compares that item to i for equality.
--
Steven
More information about the Python-list
mailing list