set using alternative hash function?

Chris Rebert clp2 at rebertia.com
Thu Oct 15 10:57:56 EDT 2009


On Thu, Oct 15, 2009 at 5:22 AM, Diez B. Roggisch <deets at nospam.web.de> wrote:
> 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.

Indeed. Good catch. :)
This is why I mark code as "completely untested".

Cheers,
Chris



More information about the Python-list mailing list