set using alternative hash function?

Diez B. Roggisch deets at nospam.web.de
Thu Oct 15 08:22:19 EDT 2009


Chris Rebert wrote:

> On Thu, Oct 15, 2009 at 4:24 AM, Austin Bingham
> <austin.bingham at gmail.com> wrote:
>> If I understand things correctly, the set class uses hash()
>> universally to calculate hash values for its elements. Is there a
>> standard way to have set use a different function? Say I've got a
>> collection of objects with names. I'd like to create a set of these
>> objects where the hashing is done on these names. Using the __hash__
>> function seems inelegant because it means I have to settle on one type
>> of hashing for these objects all of the time, i.e. I can't create a
>> set of them based on a different uniqueness criteria later. I'd like
>> to create a set instance that uses, say, 'hash(x.name)' rather than
>> 'hash(x)'.
>>
>> Is this possible? Am I just thinking about this problem the wrong way?
>> Admittedly, I'm coming at this from a C++/STL perspective, so perhaps
>> I'm just missing the obvious. Thanks for any help on this.
> 
> You could use wrapper objects that define an appropriate __hash__():
> 
> #*completely untested*
> class HashWrapper(object):
>     def __init__(self, obj, criteria):
>         self._wrapee = obj
>         self._criteria = criteria
> 
>     #override __hash__() / hash()
>     def __hash__(self):
>         return hash(self._criteria(self._wrapee))
> 
>     #proxying code
>     def __getattr__(self, name):
>         return getattr(self._wrapee, name)
> 
>     def __setattr__(self, name, val):
>         setattr(self._wrapee, name, val)

This doesn't work for conflicting elements, as the __eq__-method isn't
overriden.

Diez



More information about the Python-list mailing list