By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
455,767 Members | 1,332 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 455,767 IT Pros & Developers. It's quick & easy.

Sets and Membership Tests

P: n/a
I would like to be able use sets where the set members are objects of a
class I wrote.
I want the members to be distinguished by some of the object content,
but I have not figured out how a set determines whether two (potential)
elements are identical. I tried implementing __eq__ and __ne__ and
__hash__ to make objects with identical content behave as identical for
set membership, but so far no luck.

I could subclass set if necessary, but I still don't know what I would
need to override.

TIA for any advice you can offer.

Jul 12 '06 #1
Share this Question
Share on Google+
5 Replies


P: n/a

JKPeck wrote:
I would like to be able use sets where the set members are objects of a
class I wrote.
I want the members to be distinguished by some of the object content,
but I have not figured out how a set determines whether two (potential)
elements are identical. I tried implementing __eq__ and __ne__ and
__hash__ to make objects with identical content behave as identical for
set membership, but so far no luck.
__eq__ and __hash__ are necessary and sufficient. Code?

-Mike

Jul 12 '06 #2

P: n/a
JK,

You are correct to implement __hash__ and __eq__. The problem is how
you implemented them. Usually your __eq__ method should compare the
necessary attributes of the objects for equality. The __hash__ should
return a 32-bit integer. Your best bet is probably to return a hash of
hashes of your attributes that are used in equality comparison. What
this means is that your attributes used to produce the __hash__ should
also be hashable. This is important yet not immediatly obvious. So you
could for example return hash( (attribute1, attribute2, attribute3) ),
where attribute1, attribute2, attribute3 are all hashable.
Of course, you provided no code and no error messages (the
'SoFarNoLuck' exception is not descriptive enough ; )

Hope this helps

JKPeck wrote:
I would like to be able use sets where the set members are objects of a
class I wrote.
I want the members to be distinguished by some of the object content,
but I have not figured out how a set determines whether two (potential)
elements are identical. I tried implementing __eq__ and __ne__ and
__hash__ to make objects with identical content behave as identical for
set membership, but so far no luck.

I could subclass set if necessary, but I still don't know what I would
need to override.

TIA for any advice you can offer.
Jul 12 '06 #3

P: n/a
Thanks for the advice. Once assured that __hash__ etc was the right
route, I found that using hash() instead of object.__hash__() gave me
stable hash valules. (I am hashing strings that I know to be unique.)

The "no luck" situation was that a set would accept the same object
multiple times, not recognizing that it was truly the same object.
Nick Vatamaniuc wrote:
JK,

You are correct to implement __hash__ and __eq__. The problem is how
you implemented them. Usually your __eq__ method should compare the
necessary attributes of the objects for equality. The __hash__ should
return a 32-bit integer. Your best bet is probably to return a hash of
hashes of your attributes that are used in equality comparison. What
this means is that your attributes used to produce the __hash__ should
also be hashable. This is important yet not immediatly obvious. So you
could for example return hash( (attribute1, attribute2, attribute3) ),
where attribute1, attribute2, attribute3 are all hashable.
Of course, you provided no code and no error messages (the
'SoFarNoLuck' exception is not descriptive enough ; )

Hope this helps

JKPeck wrote:
I would like to be able use sets where the set members are objects of a
class I wrote.
I want the members to be distinguished by some of the object content,
but I have not figured out how a set determines whether two (potential)
elements are identical. I tried implementing __eq__ and __ne__ and
__hash__ to make objects with identical content behave as identical for
set membership, but so far no luck.

I could subclass set if necessary, but I still don't know what I would
need to override.

TIA for any advice you can offer.
Jul 12 '06 #4

P: n/a
JKPeck <JK****@gmail.comwrote:
Thanks for the advice. Once assured that __hash__ etc was the right
route, I found that using hash() instead of object.__hash__() gave me
stable hash valules. (I am hashing strings that I know to be unique.)

The "no luck" situation was that a set would accept the same object
multiple times, not recognizing that it was truly the same object.
Your problem may have been exactly that you were misunderstanding the
nature and functionality of object.__hash__:
>>x='guess what'
id(x)
360720
>>object.__hash__(x)
360720

As you see, what it does is return the id() of the object (that's how
objects are hashed -- if they don't implement __eq__ or __cmp__,
equality comparisons also go to the id()'s, so things work;-) -- unless
their type/class overrides __hash__). Of course, by going directly to
object.__hash__ you're explicitly *avoiding* the override, so...
Alex
Jul 12 '06 #5

P: n/a
JK,
As a general rule, let Python call the "magic" __method__ methods
behind the scenes. So don't call obj.__hash()__ or obj.__len__ or
obj.__le__ just use hash(obj), len(obj) or <=. Of course there are
exceptions, for example when calling the __init__() method of a
supercalass inside the __init__ method of your class and perhaps a few
others...
Nick V.
JKPeck wrote:
Thanks for the advice. Once assured that __hash__ etc was the right
route, I found that using hash() instead of object.__hash__() gave me
stable hash valules. (I am hashing strings that I know to be unique.)

The "no luck" situation was that a set would accept the same object
multiple times, not recognizing that it was truly the same object.
Nick Vatamaniuc wrote:
JK,

You are correct to implement __hash__ and __eq__. The problem is how
you implemented them. Usually your __eq__ method should compare the
necessary attributes of the objects for equality. The __hash__ should
return a 32-bit integer. Your best bet is probably to return a hash of
hashes of your attributes that are used in equality comparison. What
this means is that your attributes used to produce the __hash__ should
also be hashable. This is important yet not immediatly obvious. So you
could for example return hash( (attribute1, attribute2, attribute3) ),
where attribute1, attribute2, attribute3 are all hashable.
Of course, you provided no code and no error messages (the
'SoFarNoLuck' exception is not descriptive enough ; )

Hope this helps

JKPeck wrote:
I would like to be able use sets where the set members are objects of a
class I wrote.
I want the members to be distinguished by some of the object content,
but I have not figured out how a set determines whether two (potential)
elements are identical. I tried implementing __eq__ and __ne__ and
__hash__ to make objects with identical content behave as identical for
set membership, but so far no luck.
>
I could subclass set if necessary, but I still don't know what I would
need to override.
>
TIA for any advice you can offer.
Jul 12 '06 #6

This discussion thread is closed

Replies have been disabled for this discussion.